1818import  io .a2a .client .transport .spi .interceptors .auth .AuthInterceptor ;
1919import  io .a2a .common .A2AHeaders ;
2020import  io .a2a .grpc .A2AServiceGrpc ;
21+ import  io .a2a .grpc .A2AServiceGrpc .A2AServiceBlockingV2Stub ;
22+ import  io .a2a .grpc .A2AServiceGrpc .A2AServiceStub ;
2123import  io .a2a .grpc .CancelTaskRequest ;
2224import  io .a2a .grpc .CreateTaskPushNotificationConfigRequest ;
2325import  io .a2a .grpc .DeleteTaskPushNotificationConfigRequest ;
2830import  io .a2a .grpc .SendMessageResponse ;
2931import  io .a2a .grpc .StreamResponse ;
3032import  io .a2a .grpc .TaskSubscriptionRequest ;
31- 
33+ import  io .a2a .grpc .utils .ProtoUtils .FromProto ;
34+ import  io .a2a .grpc .utils .ProtoUtils .ToProto ;
3235import  io .a2a .spec .A2AClientException ;
3336import  io .a2a .spec .AgentCard ;
3437import  io .a2a .spec .DeleteTaskPushNotificationConfigParams ;
4952import  io .grpc .StatusRuntimeException ;
5053import  io .grpc .stub .MetadataUtils ;
5154import  io .grpc .stub .StreamObserver ;
55+ import  org .jspecify .annotations .Nullable ;
5256
5357public  class  GrpcTransport  implements  ClientTransport  {
5458
@@ -60,23 +64,24 @@ public class GrpcTransport implements ClientTransport {
6064            Metadata .ASCII_STRING_MARSHALLER );
6165    private  final  A2AServiceBlockingV2Stub  blockingStub ;
6266    private  final  A2AServiceStub  asyncStub ;
63-     private  final  List <ClientCallInterceptor > interceptors ;
67+     private  final  @ Nullable   List <ClientCallInterceptor > interceptors ;
6468    private  AgentCard  agentCard ;
6569
6670    public  GrpcTransport (Channel  channel , AgentCard  agentCard ) {
6771        this (channel , agentCard , null );
6872    }
6973
70-     public  GrpcTransport (Channel  channel , AgentCard  agentCard , List <ClientCallInterceptor > interceptors ) {
74+     public  GrpcTransport (Channel  channel , AgentCard  agentCard , @ Nullable   List <ClientCallInterceptor > interceptors ) {
7175        checkNotNullParam ("channel" , channel );
76+         checkNotNullParam ("agentCard" , agentCard );
7277        this .asyncStub  = A2AServiceGrpc .newStub (channel );
7378        this .blockingStub  = A2AServiceGrpc .newBlockingV2Stub (channel );
7479        this .agentCard  = agentCard ;
7580        this .interceptors  = interceptors ;
7681    }
7782
7883    @ Override 
79-     public  EventKind  sendMessage (MessageSendParams  request , ClientCallContext  context ) throws  A2AClientException  {
84+     public  EventKind  sendMessage (MessageSendParams  request , @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
8085        checkNotNullParam ("request" , request );
8186
8287        SendMessageRequest  sendMessageRequest  = createGrpcSendMessageRequest (request , context );
@@ -100,7 +105,7 @@ public EventKind sendMessage(MessageSendParams request, ClientCallContext contex
100105
101106    @ Override 
102107    public  void  sendMessageStreaming (MessageSendParams  request , Consumer <StreamingEventKind > eventConsumer ,
103-                                      Consumer <Throwable > errorConsumer , ClientCallContext  context ) throws  A2AClientException  {
108+                                      Consumer <Throwable > errorConsumer , @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
104109        checkNotNullParam ("request" , request );
105110        checkNotNullParam ("eventConsumer" , eventConsumer );
106111        SendMessageRequest  grpcRequest  = createGrpcSendMessageRequest (request , context );
@@ -117,7 +122,7 @@ public void sendMessageStreaming(MessageSendParams request, Consumer<StreamingEv
117122    }
118123
119124    @ Override 
120-     public  Task  getTask (TaskQueryParams  request , ClientCallContext  context ) throws  A2AClientException  {
125+     public  Task  getTask (TaskQueryParams  request , @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
121126        checkNotNullParam ("request" , request );
122127
123128        GetTaskRequest .Builder  requestBuilder  = GetTaskRequest .newBuilder ();
@@ -138,7 +143,7 @@ public Task getTask(TaskQueryParams request, ClientCallContext context) throws A
138143    }
139144
140145    @ Override 
141-     public  Task  cancelTask (TaskIdParams  request , ClientCallContext  context ) throws  A2AClientException  {
146+     public  Task  cancelTask (TaskIdParams  request , @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
142147        checkNotNullParam ("request" , request );
143148
144149        CancelTaskRequest  cancelTaskRequest  = CancelTaskRequest .newBuilder ()
@@ -157,7 +162,7 @@ public Task cancelTask(TaskIdParams request, ClientCallContext context) throws A
157162
158163    @ Override 
159164    public  TaskPushNotificationConfig  setTaskPushNotificationConfiguration (TaskPushNotificationConfig  request ,
160-                                                                            ClientCallContext  context ) throws  A2AClientException  {
165+                                                                            @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
161166        checkNotNullParam ("request" , request );
162167
163168        String  configId  = request .pushNotificationConfig ().id ();
@@ -180,7 +185,7 @@ public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushN
180185    @ Override 
181186    public  TaskPushNotificationConfig  getTaskPushNotificationConfiguration (
182187            GetTaskPushNotificationConfigParams  request ,
183-             ClientCallContext  context ) throws  A2AClientException  {
188+             @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
184189        checkNotNullParam ("request" , request );
185190
186191        GetTaskPushNotificationConfigRequest  grpcRequest  = GetTaskPushNotificationConfigRequest .newBuilder ()
@@ -200,7 +205,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(
200205    @ Override 
201206    public  List <TaskPushNotificationConfig > listTaskPushNotificationConfigurations (
202207            ListTaskPushNotificationConfigParams  request ,
203-             ClientCallContext  context ) throws  A2AClientException  {
208+             @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
204209        checkNotNullParam ("request" , request );
205210
206211        ListTaskPushNotificationConfigRequest  grpcRequest  = ListTaskPushNotificationConfigRequest .newBuilder ()
@@ -221,7 +226,7 @@ public List<TaskPushNotificationConfig> listTaskPushNotificationConfigurations(
221226
222227    @ Override 
223228    public  void  deleteTaskPushNotificationConfigurations (DeleteTaskPushNotificationConfigParams  request ,
224-                                                          ClientCallContext  context ) throws  A2AClientException  {
229+                                                          @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
225230        checkNotNullParam ("request" , request );
226231
227232        DeleteTaskPushNotificationConfigRequest  grpcRequest  = DeleteTaskPushNotificationConfigRequest .newBuilder ()
@@ -240,7 +245,7 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC
240245
241246    @ Override 
242247    public  void  resubscribe (TaskIdParams  request , Consumer <StreamingEventKind > eventConsumer ,
243-                             Consumer <Throwable > errorConsumer , ClientCallContext  context ) throws  A2AClientException  {
248+                             Consumer <Throwable > errorConsumer , @ Nullable   ClientCallContext  context ) throws  A2AClientException  {
244249        checkNotNullParam ("request" , request );
245250        checkNotNullParam ("eventConsumer" , eventConsumer );
246251
@@ -261,7 +266,7 @@ public void resubscribe(TaskIdParams request, Consumer<StreamingEventKind> event
261266    }
262267
263268    @ Override 
264-     public  AgentCard  getAgentCard (ClientCallContext  context ) throws  A2AClientException  {
269+     public  AgentCard  getAgentCard (@ Nullable   ClientCallContext  context ) throws  A2AClientException  {
265270        // TODO: Determine how to handle retrieving the authenticated extended agent card 
266271        return  agentCard ;
267272    }
@@ -270,7 +275,7 @@ public AgentCard getAgentCard(ClientCallContext context) throws A2AClientExcepti
270275    public  void  close () {
271276    }
272277
273-     private  SendMessageRequest  createGrpcSendMessageRequest (MessageSendParams  messageSendParams , ClientCallContext  context ) {
278+     private  SendMessageRequest  createGrpcSendMessageRequest (MessageSendParams  messageSendParams , @ Nullable   ClientCallContext  context ) {
274279        SendMessageRequest .Builder  builder  = SendMessageRequest .newBuilder ();
275280        builder .setRequest (ToProto .message (messageSendParams .message ()));
276281        if  (messageSendParams .configuration () != null ) {
@@ -285,8 +290,11 @@ private SendMessageRequest createGrpcSendMessageRequest(MessageSendParams messag
285290    /** 
286291     * Creates gRPC metadata from ClientCallContext headers. 
287292     * Extracts headers like X-A2A-Extensions and sets them as gRPC metadata. 
293+      * @param context the client call context containing headers, may be null 
294+      * @param payloadAndHeaders the payload and headers wrapper, may be null 
295+      * @return the gRPC metadata 
288296     */ 
289-     private  Metadata  createGrpcMetadata (ClientCallContext  context , PayloadAndHeaders  payloadAndHeaders ) {
297+     private  Metadata  createGrpcMetadata (@ Nullable   ClientCallContext  context ,  @ Nullable  PayloadAndHeaders  payloadAndHeaders ) {
290298        Metadata  metadata  = new  Metadata ();
291299
292300        if  (context  != null  && context .getHeaders () != null ) {
@@ -328,7 +336,7 @@ private Metadata createGrpcMetadata(ClientCallContext context, PayloadAndHeaders
328336     * @param payloadAndHeaders the payloadAndHeaders after applying any interceptors 
329337     * @return blocking stub with metadata interceptor 
330338     */ 
331-     private  A2AServiceBlockingV2Stub  createBlockingStubWithMetadata (ClientCallContext  context ,
339+     private  A2AServiceBlockingV2Stub  createBlockingStubWithMetadata (@ Nullable   ClientCallContext  context ,
332340                                                                    PayloadAndHeaders  payloadAndHeaders ) {
333341        Metadata  metadata  = createGrpcMetadata (context , payloadAndHeaders );
334342        return  blockingStub .withInterceptors (MetadataUtils .newAttachHeadersInterceptor (metadata ));
@@ -341,7 +349,7 @@ private A2AServiceBlockingV2Stub createBlockingStubWithMetadata(ClientCallContex
341349     * @param payloadAndHeaders the payloadAndHeaders after applying any interceptors 
342350     * @return async stub with metadata interceptor 
343351     */ 
344-     private  A2AServiceStub  createAsyncStubWithMetadata (ClientCallContext  context ,
352+     private  A2AServiceStub  createAsyncStubWithMetadata (@ Nullable   ClientCallContext  context ,
345353                                                       PayloadAndHeaders  payloadAndHeaders ) {
346354        Metadata  metadata  = createGrpcMetadata (context , payloadAndHeaders );
347355        return  asyncStub .withInterceptors (MetadataUtils .newAttachHeadersInterceptor (metadata ));
@@ -351,7 +359,7 @@ private String getTaskPushNotificationConfigName(GetTaskPushNotificationConfigPa
351359        return  getTaskPushNotificationConfigName (params .id (), params .pushNotificationConfigId ());
352360    }
353361
354-     private  String  getTaskPushNotificationConfigName (String  taskId , String  pushNotificationConfigId ) {
362+     private  String  getTaskPushNotificationConfigName (String  taskId , @ Nullable   String  pushNotificationConfigId ) {
355363        StringBuilder  name  = new  StringBuilder ();
356364        name .append ("tasks/" );
357365        name .append (taskId );
@@ -366,7 +374,7 @@ private String getTaskPushNotificationConfigName(String taskId, String pushNotif
366374    }
367375
368376    private  PayloadAndHeaders  applyInterceptors (String  methodName , Object  payload ,
369-                                                 AgentCard  agentCard , ClientCallContext  clientCallContext ) {
377+                                                 AgentCard  agentCard , @ Nullable   ClientCallContext  clientCallContext ) {
370378        PayloadAndHeaders  payloadAndHeaders  = new  PayloadAndHeaders (payload ,
371379                clientCallContext  != null  ? clientCallContext .getHeaders () : null );
372380        if  (interceptors  != null  && ! interceptors .isEmpty ()) {
0 commit comments