Skip to content

feat: Add 0.3 compatibility layer#797

Closed
kabir wants to merge 70 commits intoa2aproject:compat_0.3from
kabir:add-0.3-compat-reference
Closed

feat: Add 0.3 compatibility layer#797
kabir wants to merge 70 commits intoa2aproject:compat_0.3from
kabir:add-0.3-compat-reference

Conversation

@kabir
Copy link
Copy Markdown
Collaborator

@kabir kabir commented Apr 16, 2026

This passes the reference/* tests

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a v0.3 compatibility layer for the A2A SDK, including new client transport implementations (gRPC, JSON-RPC, REST) and a server-side conversion layer to map v0.3 requests to v1.0. The review identified several issues: the SSE implementation in JdkA2AHttpClient is fragile regarding message boundaries, the A2A.getAgentCard method inefficiently creates new HTTP clients, the GrpcTransport.close() method fails to shut down the channel, the gRPC getAgentCard implementation lacks support for extended cards, and the JSONRPCTransport has a potential race condition in its SSE event listener setup. Additionally, an improvement was suggested to include response bodies in HTTP error messages.

Comment thread compat-0.3/client/base/src/main/java/org/a2aproject/sdk/compat03/A2A.java Outdated
@kabir kabir force-pushed the add-0.3-compat-reference branch from b96b370 to 96797e1 Compare April 16, 2026 10:26
jmesnil and others added 5 commits April 16, 2026 16:16
a2aproject#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 <jmesnil@ibm.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes a2aproject#791 🦕

---------

Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
Signed-off-by: Emmanuel Hugonnet <ehugonne@redhat.com>
kabir and others added 22 commits April 21, 2026 14:15
Comment out usage of DefaultRequestHandler until we have the payload conversion.
Disable tests since the code is not runnable yet
…handlers

Add fully functional Quarkus reference implementations and transport handlers
for JSON-RPC and gRPC protocols with v0.3 compatibility layer.

Architecture:
- Quarkus Reference Layer (reference/*/quarkus/) routes to transport handlers
- Transport Handlers (transport/jsonrpc, grpc) contain stubbed translation layer
- Translation from v0.3 types → current SDK types will happen in handlers
- Reuses main codebase classes (ServerCallContext, TransportMetadata, etc.)

Changes:
- Add A2ACompat03Headers class with X-A2A-Extensions header constant
- Implement JSONRPCHandler with all methods stubbed for translation layer
- Implement GrpcHandler with all gRPC service methods stubbed
- Add compat-0.3 spec dependencies to transport and reference modules
- Update BOM verifiers to exclude compat-0.3 from extras/reference BOMs
- Fix TCK package names (io.a2a.tck.server → org.a2aproject.sdk.compat03.tck.server)
- Add all 16 compat-0.3 modules to SDK BOM

Modules now building successfully:
- compat-0.3/spec, spec-grpc
- compat-0.3/client/* (base + 4 transports)
- compat-0.3/transport/* (jsonrpc, grpc, rest - with translation stubs)
- compat-0.3/reference/* (common, jsonrpc, grpc, rest - fully functional)
- All BOMs (sdk, extras, reference) pass verification

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
kabir and others added 23 commits April 21, 2026 14:15
Port JSONRPC-specific test routes from 0.3.x that expose TestUtilsBean endpoints via Quarkus REST.
The ported class uses v1.0 types (Task, TaskStatusUpdateEvent, TaskPushNotificationConfig) and
v1.0 JsonUtil for serialization while maintaining the same REST endpoint patterns.

Key changes:
- Package: io.a2a.server.apps.quarkus → org.a2aproject.sdk.compat03.server.apps.quarkus
- Import v1.0 spec types: org.a2aproject.sdk.spec.*
- Import v1.0 JsonUtil: org.a2aproject.sdk.jsonrpc.common.json.JsonUtil
- Use v1.0 TestUtilsBean from tests/server-common
- PushNotificationConfig → TaskPushNotificationConfig
- Inject A2AServerRoutes for streaming subscription tracking

Endpoints exposed (10 total):
- POST /test/task - save task
- GET /test/task/:taskId - get task
- DELETE /test/task/:taskId - delete task
- POST /test/queue/ensure/:taskId - ensure queue exists
- POST /test/queue/enqueueTaskStatusUpdateEvent/:taskId - enqueue status event
- POST /test/queue/enqueueTaskArtifactUpdateEvent/:taskId - enqueue artifact event
- GET /test/streamingSubscribedCount - get subscription count
- GET /test/queue/childCount/:taskId - get child queue count
- DELETE /test/task/:taskId/config/:configId - delete push notification config
- POST /test/task/:taskId - save push notification config

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement QuarkusA2AJSONRPCTest to extend AbstractCompat03ServerTest with all
inherited test methods. Remove @disabled annotation to enable test execution.
Add required client test dependencies to pom.xml for ClientBuilder and JSONRPC
transport classes.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add META-INF/beans.xml files to enable CDI bean discovery in:
- compat-0.3/transport/jsonrpc (for JSONRPCHandler)
- compat-0.3/server-conversion (for Convert03To10RequestHandler)
- compat-0.3/reference/jsonrpc (for reference server beans)

Add test configuration:
- TestBeanProducers: Provides default AgentCard bean for testing
- application.properties: Configures Quarkus to index server-conversion
  dependency for CDI bean discovery

This fixes unsatisfied dependency errors during test startup. The server
now starts successfully and tests can run.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…tests

Fixed test server startup failures by addressing CDI bean discovery issues:

1. TestBeanProducers.createTestAgentCard(): Added required fields (url,
   description, defaultInputModes, defaultOutputModes, skills) that were
   missing from the v0.3 AgentCard builder

2. application.properties: Added classifier=tests to quarkus.index-dependency
   configuration to properly index the server-conversion test-jar containing
   AgentExecutorProducer

3. application.properties: Excluded v1.0 test producers
   (AgentExecutorProducer, AgentCardProducer) that conflict with v0.3
   compatibility layer implementations

Test results improved from 27 failures + 8 errors to 13 failures + 6 errors.
Remaining issues are push notification tests (capabilities disabled) and
JSON error serialization (Gson reflection).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed pushNotifications from false to true in TestBeanProducers.
This fixes 9 push notification test failures.

Test results improved from 13 failures + 6 errors to 3 failures + 6 errors.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added surefire argLine to open java.base/java.lang module to allow Gson
to access Throwable fields when deserializing error responses.

This fixes 6 test errors related to JSON error serialization:
- testInvalidJSONRPCRequestInvalidId
- testInvalidJSONRPCRequestMissingJsonrpc
- testInvalidJSONRPCRequestMissingMethod
- testInvalidJSONRPCRequestNonExistentMethod
- testInvalidParamsJSONRPCRequest
- testMalformedJSONRPCRequest

Test results improved from 3 failures + 6 errors to 3 failures + 0 errors.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
v1.0 introduced a feature where resubscribing to a task sends the current
task state as the first event (a TaskEvent). This is valid behavior that
v0.3 clients should accept.

Updated test consumers to accept TaskEvent as the first event only:
- testResubscribeExistingTaskSuccess
- testNonBlockingWithMultipleMessages
- testMainQueueReferenceCountingWithMultipleConsumers

Added validation using AtomicBoolean.compareAndSet() to ensure TaskEvent
only appears as the very first event, marking it as unexpected if it
appears later in the stream.

Added TODO comment to check if this initial snapshot is part of the v0.3
spec or a v1.0 enhancement.

Test results: All 37 tests now pass (was 3 failures + 0 errors).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Port v0.3 REST reference server integration tests to verify
v0.3 client → v0.3 transport → v1.0 backend conversion layer.

Changes:
- Add server-conversion test-jar and client dependencies to pom.xml
- Add Gson reflection JVM args (--add-opens java.lang)
- Create TestBeanProducers with v0.3 AgentCard (streaming + push notifications)
- Create application.properties with Quarkus CDI indexing and port 8081
- Implement QuarkusA2ARestTest extending AbstractCompat03ServerTest
- Port A2ATestRoutes to expose v1.0 TestUtilsBean via REST endpoints
- Add beans.xml to REST transport and reference modules for CDI discovery

Results: 37/37 tests run (1 failure, 9 skipped - same pattern as JSONRPC)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…tificationConfiguration

When getTaskPushNotificationConfiguration is called without a pushNotificationConfigId
(i.e., GetTaskPushNotificationConfigParams constructed with only taskId), the REST
client transport was constructing a URL with literal "null" in the path:
/v1/tasks/{taskId}/pushNotificationConfigs/null

This caused the test testGetPushNotificationSuccess to fail with "Task not found" error.

The fix uses the taskId as the default configId when pushNotificationConfigId is null,
following the convention established in the v0.3 spec where the taskId serves as the
default/primary push notification config ID.

This aligns with the server-side behavior and existing test patterns which use
taskId as configId when no specific configId is provided.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Port the testMethodNotFound test from v0.3.x QuarkusA2ARestTest. This test
verifies that REST endpoints properly reject unsupported HTTP methods with
405 (Method Not Allowed) status code.

The test sends PUT and DELETE requests to /v1/message:send (which only
accepts POST) and asserts that both return 405 status.

This brings the REST reference server test coverage to parity with the
v0.3.x implementation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Complete the v0.3 to v1.0 compatibility layer reference server test suite by porting the gRPC tests, following the same pattern as JSONRPC and REST.

Created test infrastructure:
- QuarkusA2AGrpcTest: Main test class with gRPC transport configuration
- A2ATestResource: JAX-RS endpoints exposing TestUtilsBean for test utilities
- TestBeanProducers: CDI producers for v0.3 AgentCard
- application.properties: Test configuration with gRPC settings and CDI indexing
- META-INF/beans.xml: CDI beans configuration
- META-INF/services: TransportMetadata service registration

Key implementation details:
- Uses JAX-RS for test utilities (like v0.3.x) instead of Reactive Routes
- Added quarkus.index-dependency.transport-grpc to enable gRPC service discovery
- Excluded v1.0 spec-grpc to prevent conflicts with v0.3 spec-grpc
- Added streaming subscription hook to GrpcHandler for test synchronization
- Configured maven-surefire-plugin with JVM args for Gson reflection

Test results: 37 tests passing, 0 failures, 9 skipped

All three transports now complete:
- JSONRPC: 50 tests passing
- REST: 38 tests passing
- gRPC: 37 tests passing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove empty placeholder test files that were awaiting server-common port.
These unit tests verify routing infrastructure (METHOD_NAME_KEY propagation)
which is already covered by the integration test suite (AbstractCompat03ServerTest).

The integration tests provide better end-to-end coverage:
- JSONRPC: 50 tests passing
- REST: 38 tests passing
- gRPC: 37 tests passing (never had routing unit tests)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace 4 TODO comments questioning whether TaskEvent as first event is
valid in v0.3 with spec-referencing comments confirming this behavior.

The v0.3 specification at section 7.2.1 (SendStreamingMessageResponse)
confirms that sending the current task snapshot as the first event on
resubscribe is the intended behavior.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…test-jar

Phase 2 of v0.3 compatibility layer cleanup - eliminate dependency on v1.0 test infrastructure.

Created unified test infrastructure in compat-0.3/server-conversion test-jar:
- AgentCardProducer: Produces v0.3 AgentCard with transport-specific configuration
- TestUtilsBean: Server-side test utilities (duplicated from v1.0 to avoid dependency)
- TestHttpClient: Test HTTP client implementation (duplicated from v1.0)
- beans.xml: CDI configuration for test bean discovery

Removed v1.0 test infrastructure dependency:
- Deleted a2a-java-sdk-tests-server-common dependencies from reference module POMs
- Removed duplicate TestBeanProducers from jsonrpc/rest/grpc reference modules
- Updated application.properties to use v0.3 compat test infrastructure

Transport-specific configuration:
- Created compat-0.3-requesthandler-test.properties for each transport
- JSONRPC: preferred-transport=jsonrpc
- REST: preferred-transport=rest
- gRPC: preferred-transport=grpc

Test results: 112 tests passing (37 JSONRPC + 37 gRPC + 38 REST, 18 skipped)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Use registerTypeAdapter for Throwable instead of registerTypeHierarchyAdapter
to prevent adapter from matching JSONRPCError subclasses. This allows proper
adapter selection without requiring --add-opens JVM flag.

Changes:
- JsonUtil: Use registerTypeAdapter(Throwable.class) for exact type matching
- Remove --add-opens java.base/java.lang=ALL-UNNAMED from all reference POMs
- Add V03GsonObjectMapper for deserializing v0.3 JSONRPC error responses
- Add givenV03() helper in AbstractCompat03ServerTest for error tests

All 112 reference tests pass without JVM args.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@kabir kabir changed the base branch from main to compat_0.3 April 21, 2026 12:20
@kabir kabir force-pushed the add-0.3-compat-reference branch from 151f92a to 2c0ac9c Compare April 21, 2026 13:22
@kabir kabir closed this Apr 21, 2026
@kabir kabir deleted the add-0.3-compat-reference branch April 21, 2026 13:37
@kabir
Copy link
Copy Markdown
Collaborator Author

kabir commented Apr 21, 2026

Superseded by #805

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants