Skip to content

Commit 0577dd5

Browse files
committed
Merge branch 'main' into update-grpc
2 parents 4cb3141 + c154104 commit 0577dd5

File tree

240 files changed

+10692
-6609
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

240 files changed

+10692
-6609
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ We copy https://github.com/a2aproject/A2A/blob/main/specification/grpc/a2a.proto
2424
```
2525
option java_package = "io.a2a.grpc";
2626
```
27-
Then build the `spec-grpc` module with `mvn clean install -Pproto-compile` to regenerate the gRPC classes in the `io.a2a.grpc` package.
27+
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.
2828

2929
## Examples
3030

boms/sdk/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@
155155
<dependency>
156156
<groupId>com.google.protobuf</groupId>
157157
<artifactId>protobuf-java</artifactId>
158-
<version>${protobuf.version}</version>
158+
<version>${protobuf-java.version}</version>
159159
</dependency>
160160
<dependency>
161161
<groupId>io.smallrye.reactive</groupId>

client/base/src/main/java/io/a2a/client/ClientBuilder.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,29 +92,29 @@ private ClientTransport buildClientTransport() throws A2AClientException {
9292
AgentInterface agentInterface = findBestClientTransport();
9393

9494
// Get the transport provider associated with the protocol
95-
ClientTransportProvider clientTransportProvider = transportProviderRegistry.get(agentInterface.transport());
95+
ClientTransportProvider clientTransportProvider = transportProviderRegistry.get(agentInterface.protocolBinding());
9696
if (clientTransportProvider == null) {
97-
throw new A2AClientException("No client available for " + agentInterface.transport());
97+
throw new A2AClientException("No client available for " + agentInterface.protocolBinding());
9898
}
9999
Class<? extends ClientTransport> transportProtocolClass = clientTransportProvider.getTransportProtocolClass();
100100

101101
// Retrieve the configuration associated with the preferred transport
102102
ClientTransportConfig<? extends ClientTransport> clientTransportConfig = clientTransports.get(transportProtocolClass);
103103

104104
if (clientTransportConfig == null) {
105-
throw new A2AClientException("Missing required TransportConfig for " + agentInterface.transport());
105+
throw new A2AClientException("Missing required TransportConfig for " + agentInterface.protocolBinding());
106106
}
107107

108108
return clientTransportProvider.create(clientTransportConfig, agentCard, agentInterface.url());
109109
}
110110

111-
private Map<String, String> getServerPreferredTransports() {
111+
private Map<String, String> getServerPreferredTransports() throws A2AClientException {
112112
Map<String, String> serverPreferredTransports = new LinkedHashMap<>();
113-
serverPreferredTransports.put(agentCard.preferredTransport(), agentCard.url());
114-
if (agentCard.additionalInterfaces() != null) {
115-
for (AgentInterface agentInterface : agentCard.additionalInterfaces()) {
116-
serverPreferredTransports.putIfAbsent(agentInterface.transport(), agentInterface.url());
117-
}
113+
if(agentCard.supportedInterfaces() == null || agentCard.supportedInterfaces().isEmpty()) {
114+
throw new A2AClientException("No server interface available in the AgentCard");
115+
}
116+
for (AgentInterface agentInterface : agentCard.supportedInterfaces()) {
117+
serverPreferredTransports.putIfAbsent(agentInterface.protocolBinding(), agentInterface.url());
118118
}
119119
return serverPreferredTransports;
120120
}

client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ public void setUp() {
7777
agentCard = new AgentCard.Builder()
7878
.name("Test Agent")
7979
.description("Test agent for auth tests")
80-
.url(AGENT_URL)
8180
.version("1.0.0")
8281
.capabilities(new AgentCapabilities.Builder()
8382
.streaming(true) // Support streaming for all tests
@@ -91,7 +90,7 @@ public void setUp() {
9190
.tags(Collections.singletonList("test"))
9291
.build()))
9392
.protocolVersion("0.3.0")
94-
.additionalInterfaces(java.util.Arrays.asList(
93+
.supportedInterfaces(java.util.Arrays.asList(
9594
new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL),
9695
new AgentInterface(TransportProtocol.HTTP_JSON.asString(), AGENT_URL),
9796
new AgentInterface(TransportProtocol.GRPC.asString(), grpcServerName)))

client/base/src/test/java/io/a2a/client/ClientBuilderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class ClientBuilderTest {
2424
private AgentCard card = new AgentCard.Builder()
2525
.name("Hello World Agent")
2626
.description("Just a hello world agent")
27-
.url("http://localhost:9999")
27+
.supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999")))
2828
.version("1.0.0")
2929
.documentationUrl("http://example.com/docs")
3030
.capabilities(new AgentCapabilities.Builder()

client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,32 @@
1616
import io.a2a.grpc.A2AServiceGrpc;
1717
import io.a2a.grpc.A2AServiceGrpc.A2AServiceBlockingV2Stub;
1818
import io.a2a.grpc.A2AServiceGrpc.A2AServiceStub;
19-
import io.a2a.grpc.CancelTaskRequest;
20-
import io.a2a.grpc.CreateTaskPushNotificationConfigRequest;
21-
import io.a2a.grpc.DeleteTaskPushNotificationConfigRequest;
22-
import io.a2a.grpc.GetTaskPushNotificationConfigRequest;
23-
import io.a2a.grpc.GetTaskRequest;
24-
import io.a2a.grpc.ListTaskPushNotificationConfigRequest;
25-
import io.a2a.grpc.ListTasksRequest;
26-
import io.a2a.grpc.SendMessageRequest;
27-
import io.a2a.grpc.SendMessageResponse;
28-
import io.a2a.grpc.StreamResponse;
29-
import io.a2a.grpc.TaskSubscriptionRequest;
3019
import io.a2a.grpc.utils.ProtoUtils.FromProto;
3120
import io.a2a.grpc.utils.ProtoUtils.ToProto;
3221
import io.a2a.spec.A2AClientException;
3322
import io.a2a.spec.AgentCard;
23+
import io.a2a.spec.CancelTaskRequest;
3424
import io.a2a.spec.DeleteTaskPushNotificationConfigParams;
25+
import io.a2a.spec.DeleteTaskPushNotificationConfigRequest;
3526
import io.a2a.spec.EventKind;
3627
import io.a2a.spec.GetTaskPushNotificationConfigParams;
28+
import io.a2a.spec.GetTaskPushNotificationConfigRequest;
29+
import io.a2a.spec.GetTaskRequest;
3730
import io.a2a.spec.ListTaskPushNotificationConfigParams;
31+
import io.a2a.spec.ListTaskPushNotificationConfigRequest;
3832
import io.a2a.spec.ListTasksParams;
33+
import io.a2a.spec.ListTasksRequest;
3934
import io.a2a.spec.ListTasksResult;
4035
import io.a2a.spec.MessageSendParams;
36+
import io.a2a.spec.SendMessageRequest;
4137
import io.a2a.spec.SendStreamingMessageRequest;
4238
import io.a2a.spec.SetTaskPushNotificationConfigRequest;
4339
import io.a2a.spec.StreamingEventKind;
40+
import io.a2a.spec.SubscribeToTaskRequest;
4441
import io.a2a.spec.Task;
4542
import io.a2a.spec.TaskIdParams;
4643
import io.a2a.spec.TaskPushNotificationConfig;
4744
import io.a2a.spec.TaskQueryParams;
48-
import io.a2a.spec.TaskResubscriptionRequest;
4945
import io.grpc.Channel;
5046
import io.grpc.Metadata;
5147
import io.grpc.StatusException;
@@ -84,13 +80,13 @@ public GrpcTransport(Channel channel, AgentCard agentCard, @Nullable List<Client
8480
public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException {
8581
checkNotNullParam("request", request);
8682

87-
SendMessageRequest sendMessageRequest = createGrpcSendMessageRequest(request, context);
88-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(io.a2a.spec.SendMessageRequest.METHOD, sendMessageRequest,
83+
io.a2a.grpc.SendMessageRequest sendMessageRequest = createGrpcSendMessageRequest(request, context);
84+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(SendMessageRequest.METHOD, sendMessageRequest,
8985
agentCard, context);
9086

9187
try {
9288
A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders);
93-
SendMessageResponse response = stubWithMetadata.sendMessage(sendMessageRequest);
89+
io.a2a.grpc.SendMessageResponse response = stubWithMetadata.sendMessage(sendMessageRequest);
9490
if (response.hasMsg()) {
9591
return FromProto.message(response.getMsg());
9692
} else if (response.hasTask()) {
@@ -108,10 +104,10 @@ public void sendMessageStreaming(MessageSendParams request, Consumer<StreamingEv
108104
Consumer<Throwable> errorConsumer, @Nullable ClientCallContext context) throws A2AClientException {
109105
checkNotNullParam("request", request);
110106
checkNotNullParam("eventConsumer", eventConsumer);
111-
SendMessageRequest grpcRequest = createGrpcSendMessageRequest(request, context);
107+
io.a2a.grpc.SendMessageRequest grpcRequest = createGrpcSendMessageRequest(request, context);
112108
PayloadAndHeaders payloadAndHeaders = applyInterceptors(SendStreamingMessageRequest.METHOD,
113109
grpcRequest, agentCard, context);
114-
StreamObserver<StreamResponse> streamObserver = new EventStreamObserver(eventConsumer, errorConsumer);
110+
StreamObserver<io.a2a.grpc.StreamResponse> streamObserver = new EventStreamObserver(eventConsumer, errorConsumer);
115111

116112
try {
117113
A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders);
@@ -125,11 +121,11 @@ public void sendMessageStreaming(MessageSendParams request, Consumer<StreamingEv
125121
public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException {
126122
checkNotNullParam("request", request);
127123

128-
GetTaskRequest.Builder requestBuilder = GetTaskRequest.newBuilder();
124+
io.a2a.grpc.GetTaskRequest.Builder requestBuilder = io.a2a.grpc.GetTaskRequest.newBuilder();
129125
requestBuilder.setName("tasks/" + request.id());
130126
requestBuilder.setHistoryLength(request.historyLength());
131-
GetTaskRequest getTaskRequest = requestBuilder.build();
132-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(io.a2a.spec.GetTaskRequest.METHOD, getTaskRequest,
127+
io.a2a.grpc.GetTaskRequest getTaskRequest = requestBuilder.build();
128+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetTaskRequest.METHOD, getTaskRequest,
133129
agentCard, context);
134130

135131
try {
@@ -144,10 +140,10 @@ public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context
144140
public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException {
145141
checkNotNullParam("request", request);
146142

147-
CancelTaskRequest cancelTaskRequest = CancelTaskRequest.newBuilder()
143+
io.a2a.grpc.CancelTaskRequest cancelTaskRequest = io.a2a.grpc.CancelTaskRequest.newBuilder()
148144
.setName("tasks/" + request.id())
149145
.build();
150-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(io.a2a.spec.CancelTaskRequest.METHOD, cancelTaskRequest,
146+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(CancelTaskRequest.METHOD, cancelTaskRequest,
151147
agentCard, context);
152148

153149
try {
@@ -162,35 +158,37 @@ public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context
162158
public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException {
163159
checkNotNullParam("request", request);
164160

165-
ListTasksRequest.Builder requestBuilder = ListTasksRequest.newBuilder();
161+
io.a2a.grpc.ListTasksRequest.Builder builder = io.a2a.grpc.ListTasksRequest.newBuilder();
166162
if (request.contextId() != null) {
167-
requestBuilder.setContextId(request.contextId());
163+
builder.setContextId(request.contextId());
168164
}
169165
if (request.status() != null) {
170-
requestBuilder.setStatus(ToProto.taskState(request.status()));
166+
builder.setStatus(ToProto.taskState(request.status()));
171167
}
172168
if (request.pageSize() != null) {
173-
requestBuilder.setPageSize(request.pageSize());
169+
builder.setPageSize(request.pageSize());
174170
}
175171
if (request.pageToken() != null) {
176-
requestBuilder.setPageToken(request.pageToken());
172+
builder.setPageToken(request.pageToken());
177173
}
178174
if (request.historyLength() != null) {
179-
requestBuilder.setHistoryLength(request.historyLength());
175+
builder.setHistoryLength(request.historyLength());
180176
}
181-
if (request.includeArtifacts() != null && request.includeArtifacts()) {
182-
requestBuilder.setIncludeArtifacts(true);
177+
if (request.lastUpdatedAfter() != null) {
178+
builder.setLastUpdatedAfter(request.lastUpdatedAfter().toEpochMilli());
183179
}
184-
185-
ListTasksRequest listTasksRequest = requestBuilder.build();
186-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(io.a2a.spec.ListTasksRequest.METHOD, listTasksRequest,
180+
if (request.includeArtifacts() != null) {
181+
builder.setIncludeArtifacts(request.includeArtifacts());
182+
}
183+
io.a2a.grpc.ListTasksRequest listTasksRequest = builder.build();
184+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(ListTasksRequest.METHOD, listTasksRequest,
187185
agentCard, context);
188186

189187
try {
190188
A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders);
191189
io.a2a.grpc.ListTasksResponse grpcResponse = stubWithMetadata.listTasks(listTasksRequest);
192190

193-
return new io.a2a.spec.ListTasksResult(
191+
return new ListTasksResult(
194192
grpcResponse.getTasksList().stream()
195193
.map(FromProto::task)
196194
.collect(Collectors.toList()),
@@ -209,7 +207,7 @@ public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushN
209207
checkNotNullParam("request", request);
210208

211209
String configId = request.pushNotificationConfig().id();
212-
CreateTaskPushNotificationConfigRequest grpcRequest = CreateTaskPushNotificationConfigRequest.newBuilder()
210+
io.a2a.grpc.SetTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder()
213211
.setParent("tasks/" + request.taskId())
214212
.setConfig(ToProto.taskPushNotificationConfig(request))
215213
.setConfigId(configId != null ? configId : request.taskId())
@@ -219,8 +217,8 @@ public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushN
219217

220218
try {
221219
A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders);
222-
return FromProto.taskPushNotificationConfig(stubWithMetadata.createTaskPushNotificationConfig(grpcRequest));
223-
} catch (StatusRuntimeException | StatusException e) {
220+
return FromProto.taskPushNotificationConfig(stubWithMetadata.setTaskPushNotificationConfig(grpcRequest));
221+
} catch (StatusRuntimeException e) {
224222
throw GrpcErrorMapper.mapGrpcError(e, "Failed to create task push notification config: ");
225223
}
226224
}
@@ -231,10 +229,10 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(
231229
@Nullable ClientCallContext context) throws A2AClientException {
232230
checkNotNullParam("request", request);
233231

234-
GetTaskPushNotificationConfigRequest grpcRequest = GetTaskPushNotificationConfigRequest.newBuilder()
232+
io.a2a.grpc.GetTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder()
235233
.setName(getTaskPushNotificationConfigName(request))
236234
.build();
237-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(io.a2a.spec.GetTaskPushNotificationConfigRequest.METHOD,
235+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetTaskPushNotificationConfigRequest.METHOD,
238236
grpcRequest, agentCard, context);
239237

240238
try {
@@ -251,10 +249,10 @@ public List<TaskPushNotificationConfig> listTaskPushNotificationConfigurations(
251249
@Nullable ClientCallContext context) throws A2AClientException {
252250
checkNotNullParam("request", request);
253251

254-
ListTaskPushNotificationConfigRequest grpcRequest = ListTaskPushNotificationConfigRequest.newBuilder()
252+
io.a2a.grpc.ListTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder()
255253
.setParent("tasks/" + request.id())
256254
.build();
257-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(io.a2a.spec.ListTaskPushNotificationConfigRequest.METHOD,
255+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(ListTaskPushNotificationConfigRequest.METHOD,
258256
grpcRequest, agentCard, context);
259257

260258
try {
@@ -272,10 +270,10 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC
272270
@Nullable ClientCallContext context) throws A2AClientException {
273271
checkNotNullParam("request", request);
274272

275-
DeleteTaskPushNotificationConfigRequest grpcRequest = DeleteTaskPushNotificationConfigRequest.newBuilder()
273+
io.a2a.grpc.DeleteTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder()
276274
.setName(getTaskPushNotificationConfigName(request.id(), request.pushNotificationConfigId()))
277275
.build();
278-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(io.a2a.spec.DeleteTaskPushNotificationConfigRequest.METHOD,
276+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(DeleteTaskPushNotificationConfigRequest.METHOD,
279277
grpcRequest, agentCard, context);
280278

281279
try {
@@ -292,17 +290,17 @@ public void resubscribe(TaskIdParams request, Consumer<StreamingEventKind> event
292290
checkNotNullParam("request", request);
293291
checkNotNullParam("eventConsumer", eventConsumer);
294292

295-
TaskSubscriptionRequest grpcRequest = TaskSubscriptionRequest.newBuilder()
293+
io.a2a.grpc.SubscribeToTaskRequest grpcRequest = io.a2a.grpc.SubscribeToTaskRequest.newBuilder()
296294
.setName("tasks/" + request.id())
297295
.build();
298-
PayloadAndHeaders payloadAndHeaders = applyInterceptors(TaskResubscriptionRequest.METHOD,
296+
PayloadAndHeaders payloadAndHeaders = applyInterceptors(SubscribeToTaskRequest.METHOD,
299297
grpcRequest, agentCard, context);
300298

301-
StreamObserver<StreamResponse> streamObserver = new EventStreamObserver(eventConsumer, errorConsumer);
299+
StreamObserver<io.a2a.grpc.StreamResponse> streamObserver = new EventStreamObserver(eventConsumer, errorConsumer);
302300

303301
try {
304302
A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders);
305-
stubWithMetadata.taskSubscription(grpcRequest, streamObserver);
303+
stubWithMetadata.subscribeToTask(grpcRequest, streamObserver);
306304
} catch (StatusRuntimeException e) {
307305
throw GrpcErrorMapper.mapGrpcError(e, "Failed to resubscribe task push notification config: ");
308306
}
@@ -318,16 +316,8 @@ public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2ACli
318316
public void close() {
319317
}
320318

321-
private SendMessageRequest createGrpcSendMessageRequest(MessageSendParams messageSendParams, @Nullable ClientCallContext context) {
322-
SendMessageRequest.Builder builder = SendMessageRequest.newBuilder();
323-
builder.setRequest(ToProto.message(messageSendParams.message()));
324-
if (messageSendParams.configuration() != null) {
325-
builder.setConfiguration(ToProto.messageSendConfiguration(messageSendParams.configuration()));
326-
}
327-
if (messageSendParams.metadata() != null) {
328-
builder.setMetadata(ToProto.struct(messageSendParams.metadata()));
329-
}
330-
return builder.build();
319+
private io.a2a.grpc.SendMessageRequest createGrpcSendMessageRequest(MessageSendParams messageSendParams, @Nullable ClientCallContext context) {
320+
return ToProto.sendMessageRequest(messageSendParams);
331321
}
332322

333323
/**

0 commit comments

Comments
 (0)