Skip to content

Commit 9a60054

Browse files
authored
Merge branch 'main' into dependabot/maven/no.entur.mapstruct.spi-protobuf-spi-impl-1.53.0
2 parents 60ac47e + 575e3d4 commit 9a60054

45 files changed

Lines changed: 914 additions & 105 deletions

File tree

Some content is hidden

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

.claude/architecture/compatibility_0.3.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,18 @@ These fields coexist alongside the v1.0 `supportedInterfaces` field. v1.0 client
168168

169169
`Legacy_0_3_AgentInterface` is a separate record from `AgentInterface` because they serialize to different JSON field names (`transport`/`url` vs `protocolBinding`/`url`/`tenant`).
170170

171+
### Version-Aware Push Notifications
172+
173+
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:
174+
175+
1. `BasePushNotificationSender` retrieves the protocol version stored alongside each push notification configuration
176+
2. It looks up a `PushNotificationPayloadFormatter` matching that version (discovered via CDI)
177+
3. The formatter serializes the payload in the appropriate wire format:
178+
- **v0.3** (`PushNotificationPayloadFormatter_v0_3`): sends a v0.3 `Task` JSON object, skipping `Message` events (not supported in v0.3 push notifications)
179+
- **v1.0** (default): sends a `StreamResponse` wrapper containing the event
180+
181+
If no protocol version is stored (e.g., for configurations created before this feature), the version defaults to `AgentInterface.CURRENT_PROTOCOL_VERSION` (`"1.0"`).
182+
171183
---
172184

173185
## Module Structure
@@ -436,7 +448,7 @@ AgentCard card = // ... fetch agent card from /.well-known/agent-card.json
436448

437449
// Find the v0.3 interface from the agent card
438450
AgentInterface v03Interface = card.supportedInterfaces().stream()
439-
.filter(iface -> "0.3".equals(iface.protocolVersion()))
451+
.filter(iface -> A2AProtocol_v0_3.PROTOCOL_VERSION.equals(iface.protocolVersion()))
440452
.findFirst()
441453
.orElseThrow();
442454

@@ -536,10 +548,10 @@ For JSON-RPC and REST, multi-version convenience modules are also available that
536548

537549
## Status
538550

539-
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.
551+
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.
540552

541553
🔲 **Outstanding:**
542-
- Push notification test porting (requires TestHttpClient; version-aware push notifications in PR #857)
554+
- Push notification test porting (requires TestHttpClient)
543555
- Test metadata classes (classpath scanning)
544556
- Replace FQNs with imports (97 occurrences in 34 files)
545557
- Unify AgentCard producers across reference modules

.github/workflows/run-tck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
env:
1313
# Tag/branch of the TCK
1414
TCK_VERSION: 1.0-dev
15-
TCK_VERSION_0_3: 0.3.0.beta4
15+
TCK_VERSION_0_3: 0.3.x
1616
# Tells uv to not need a venv, and instead use system
1717
UV_SYSTEM_PYTHON: 1
1818
SUT_URL: http://localhost:9999

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ The two interface lists serve different clients:
373373
- `additionalInterfaces` — used by **v0.3 clients** to discover endpoints (uses `Legacy_0_3_AgentInterface` with v0.3 field names: `transport`/`url`)
374374
- `url` and `preferredTransport` — top-level fields that v0.3 clients use to discover the primary endpoint
375375

376+
#### Push Notification Behavior
377+
378+
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.
379+
376380
## A2A Client
377381

378382
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();
776780

777781
// Find the v0.3 interface from the agent card
778782
AgentInterface v03Interface = card.supportedInterfaces().stream()
779-
.filter(iface -> "0.3".equals(iface.protocolVersion()))
783+
.filter(iface -> A2AProtocol_v0_3.PROTOCOL_VERSION.equals(iface.protocolVersion()))
780784
.findFirst()
781785
.orElseThrow();
782786

boms/extras/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
<plugin>
103103
<groupId>org.apache.maven.plugins</groupId>
104104
<artifactId>maven-invoker-plugin</artifactId>
105-
<version>3.10.0</version>
105+
<version>3.10.1</version>
106106
<configuration>
107107
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
108108
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>

boms/reference/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
<plugin>
113113
<groupId>org.apache.maven.plugins</groupId>
114114
<artifactId>maven-invoker-plugin</artifactId>
115-
<version>3.10.0</version>
115+
<version>3.10.1</version>
116116
<configuration>
117117
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
118118
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>

boms/sdk/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@
291291
<plugin>
292292
<groupId>org.apache.maven.plugins</groupId>
293293
<artifactId>maven-invoker-plugin</artifactId>
294-
<version>3.10.0</version>
294+
<version>3.10.1</version>
295295
<configuration>
296296
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
297297
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>

compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/A2AServerRoutes_v0_3.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.vertx.ext.web.RoutingContext;
3434
import io.vertx.ext.web.handler.BodyHandler;
3535
import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3;
36+
import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3;
3637
import org.a2aproject.sdk.compat03.json.JsonProcessingException_v0_3;
3738
import org.a2aproject.sdk.compat03.json.JsonUtil_v0_3;
3839
import org.a2aproject.sdk.compat03.spec.AgentCard_v0_3;
@@ -327,7 +328,7 @@ public String getUsername() {
327328
List<String> extensionHeaderValues = rc.request().headers().getAll(A2AHeaders_v0_3.X_A2A_EXTENSIONS);
328329
Set<String> requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues);
329330

330-
return new ServerCallContext(user, state, requestedExtensions);
331+
return new ServerCallContext(user, state, requestedExtensions, A2AProtocol_v0_3.PROTOCOL_VERSION);
331332
} else {
332333
CallContextFactory_v0_3 builder = callContextFactory.get();
333334
return builder.build(rc);

compat-0.3/reference/jsonrpc/src/main/java/org/a2aproject/sdk/compat03/server/apps/quarkus/CallContextFactory_v0_3.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
import org.a2aproject.sdk.server.ServerCallContext;
44
import io.vertx.ext.web.RoutingContext;
55

6+
/**
7+
* Factory interface for creating ServerCallContext from a Vert.x RoutingContext.
8+
*
9+
* <p>Implementations MUST pass {@link org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3#PROTOCOL_VERSION}
10+
* as the protocol version when constructing {@link ServerCallContext} so that push notification
11+
* payloads are formatted correctly.</p>
12+
*/
613
public interface CallContextFactory_v0_3 {
714
ServerCallContext build(RoutingContext rc);
815
}

compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/A2AServerRoutes_v0_3.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.vertx.ext.web.RoutingContext;
3434
import io.vertx.ext.web.handler.BodyHandler;
3535
import org.a2aproject.sdk.compat03.common.A2AHeaders_v0_3;
36+
import org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3;
3637
import org.a2aproject.sdk.compat03.spec.CancelTaskRequest_v0_3;
3738
import org.a2aproject.sdk.compat03.spec.DeleteTaskPushNotificationConfigRequest_v0_3;
3839
import org.a2aproject.sdk.compat03.spec.GetTaskPushNotificationConfigRequest_v0_3;
@@ -431,7 +432,7 @@ public String getUsername() {
431432
List<String> extensionHeaderValues = rc.request().headers().getAll(A2AHeaders_v0_3.X_A2A_EXTENSIONS);
432433
Set<String> requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues);
433434

434-
return new ServerCallContext(user, state, requestedExtensions);
435+
return new ServerCallContext(user, state, requestedExtensions, A2AProtocol_v0_3.PROTOCOL_VERSION);
435436
} else {
436437
CallContextFactory_v0_3 builder = callContextFactory.get();
437438
return builder.build(rc);

compat-0.3/reference/rest/src/main/java/org/a2aproject/sdk/compat03/server/rest/quarkus/CallContextFactory_v0_3.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
import org.a2aproject.sdk.server.ServerCallContext;
44
import io.vertx.ext.web.RoutingContext;
55

6+
/**
7+
* Factory interface for creating ServerCallContext from a Vert.x RoutingContext.
8+
*
9+
* <p>Implementations MUST pass {@link org.a2aproject.sdk.compat03.conversion.A2AProtocol_v0_3#PROTOCOL_VERSION}
10+
* as the protocol version when constructing {@link ServerCallContext} so that push notification
11+
* payloads are formatted correctly.</p>
12+
*/
613
public interface CallContextFactory_v0_3 {
714
ServerCallContext build(RoutingContext rc);
815
}

0 commit comments

Comments
 (0)