diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml
new file mode 100644
index 0000000..a44c4de
--- /dev/null
+++ b/.github/workflows/run-tck.yml
@@ -0,0 +1,80 @@
+name: Build and Run TCK
+
+on:
+ push:
+ branches:
+# - main
+ pull_request:
+ branches:
+# - main
+
+
+env:
+ # Tag of the TCK
+ TCK_VERSION: v0.2.3
+ # Tells uv to not need a venv, and instead use system
+ UV_SYSTEM_PYTHON: 1
+
+
+# Only run the latest job
+concurrency:
+ group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}'
+ cancel-in-progress: true
+
+jobs:
+ build-and-test:
+ name: Run TCK
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Checkout a2a-java
+ uses: actions/checkout@v4
+ with:
+ repository: a2aproject/a2a-java
+ path: a2a-java
+ - name: Checkout a2a-tck
+ uses: actions/checkout@v4
+ with:
+ repository: a2aproject/a2a-tck
+ path: a2a-tck
+ ref: ${{ env.TCK_VERSION }}
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: maven
+ - name: Build a2a-java with Maven, skipping tests
+ run: |
+ mvn -B install -DskipTests
+ working-directory: a2a-java
+ - name: Get a2a-java version and save as env var
+ run: |
+ VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
+ echo "SDK_VERSION=${VERSION}" >> "$GITHUB_ENV"
+ working-directory: a2a-java
+ - name: Build the TCK server
+ run: |
+ mvn clean install -B -Dversion.sdk=${SDK_VERSION} -pl tck -am
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ 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 the WildFly SUT
+ run: |
+ mvn wildfly:start -B -pl tck -Dstartup-timeout=120
+ - name: Run TCK
+ run: |
+ ./run_tck.py --sut-url http://localhost:8080 --category all --compliance-report report.json
+ working-directory: a2a-tck
+ - name: Start the WildFly SUT
+ run: |
+ mvn wildfly:shutdown
+
+
diff --git a/pom.xml b/pom.xml
index a715565..5575236 100644
--- a/pom.xml
+++ b/pom.xml
@@ -178,51 +178,11 @@
org.wildfly.glow
wildfly-glow-arquillian-plugin
1.4.1.Final
-
-
-
- org.wildfly
- wildfly-galleon-pack
- ${version.wildfly}
-
-
- standalone.xml
-
-
-
- scan
-
- scan
-
- test-compile
-
-
org.wildfly.plugins
wildfly-maven-plugin
5.1.3.Final
-
- ${project.build.directory}/glow-scan/provisioning.xml
- ${jboss.home}
- ${jboss.home}
-
-
-
-
-
-
-
-
-
-
- test-provisioning
-
- package
-
- test-compile
-
-
org.apache.maven.plugins
@@ -286,6 +246,7 @@
impl
wildfly-jar
+ tck
tests/common
tests/impl
tests/wildfly-jar
diff --git a/tck/pom.xml b/tck/pom.xml
new file mode 100644
index 0000000..9dd0446
--- /dev/null
+++ b/tck/pom.xml
@@ -0,0 +1,84 @@
+
+
+ 4.0.0
+
+
+ org.wildfly.extras.a2a
+ a2a-java-sdk-server-jakarta-parent
+ 0.2.3.Beta2-SNAPSHOT
+
+
+ a2a-java-sdk-server-jakarta-tck-wildfly
+
+ war
+
+ WildFly Extras - Java A2A SDK for Jakarta - TCK - WildFly Jar
+ Java SDK for the Agent2Agent Protocol (A2A) - SDK - Jakarta - TCK - WildFly Jar
+
+
+
+ ${project.groupId}
+ a2a-java-sdk-server-jakarta-wildfly
+ ${project.version}
+
+
+ *
+ *
+
+
+
+
+ io.github.a2asdk
+ a2a-java-sdk-spec
+ provided
+
+
+ jakarta.annotation
+ jakarta.annotation-api
+ provided
+
+
+ jakarta.enterprise
+ jakarta.enterprise.cdi-api
+ provided
+
+
+ jakarta.ws.rs
+ jakarta.ws.rs-api
+ provided
+
+
+
+
+
+ org.wildfly.plugins
+ wildfly-maven-plugin
+
+
+
+ ${jboss.home}
+ ROOT.war
+ ${jboss.home}
+
+
+
+
+
+
+
+
+
+
+ provisioning
+
+ package
+
+ package
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/AgentCardProducer.java b/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/AgentCardProducer.java
new file mode 100644
index 0000000..48476c7
--- /dev/null
+++ b/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/AgentCardProducer.java
@@ -0,0 +1,46 @@
+package org.wildfly.extras.a2a.server.jakarta.tck;
+
+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.AgentSkill;
+
+/**
+ * This is a copy of the AgentCardProducer from the a2a-java SDK's tck/ module
+ */
+@ApplicationScoped
+public class AgentCardProducer {
+
+ @Produces
+ @PublicAgentCard
+ public AgentCard agentCard() {
+ return new AgentCard.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.Builder()
+ .streaming(true)
+ .pushNotifications(true)
+ .stateTransitionHistory(true)
+ .build())
+ .defaultInputModes(Collections.singletonList("text"))
+ .defaultOutputModes(Collections.singletonList("text"))
+ .skills(Collections.singletonList(new 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();
+ }
+}
+
diff --git a/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/AgentExecutorProducer.java b/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/AgentExecutorProducer.java
new file mode 100644
index 0000000..4a2df0c
--- /dev/null
+++ b/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/AgentExecutorProducer.java
@@ -0,0 +1,94 @@
+package org.wildfly.extras.a2a.server.jakarta.tck;
+
+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.spec.JSONRPCError;
+import io.a2a.spec.Task;
+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;
+
+/**
+ * This is a copy of the AgentExecutorProducer from the a2a-java SDK's tck/ module
+ */
+@ApplicationScoped
+public class AgentExecutorProducer {
+
+ @Produces
+ public AgentExecutor agentExecutor() {
+ return new FireAndForgetAgentExecutor();
+ }
+
+ private static class FireAndForgetAgentExecutor implements AgentExecutor {
+ @Override
+ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError {
+ Task task = context.getTask();
+
+ if (context.getMessage().getTaskId() != null && task == null && context.getMessage().getTaskId().startsWith("non-existent")) {
+ throw new TaskNotFoundError();
+ }
+
+ if (task == null) {
+ task = new Task.Builder()
+ .id(context.getTaskId())
+ .contextId(context.getContextId())
+ .status(new TaskStatus(TaskState.SUBMITTED))
+ .history(context.getMessage())
+ .build();
+ eventQueue.enqueueEvent(task);
+ }
+
+ TaskUpdater updater = new TaskUpdater(context, eventQueue);
+
+ // Immediately set to WORKING state
+ updater.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, EventQueue eventQueue) throws JSONRPCError {
+ System.out.println("====> task cancel request received");
+ Task task = context.getTask();
+
+ if (task.getStatus().state() == TaskState.CANCELED) {
+ System.out.println("====> task already canceled");
+ throw new TaskNotCancelableError();
+ }
+
+ if (task.getStatus().state() == TaskState.COMPLETED) {
+ System.out.println("====> task already completed");
+ throw new TaskNotCancelableError();
+ }
+
+ TaskUpdater updater = new TaskUpdater(context, eventQueue);
+ updater.cancel();
+ eventQueue.enqueueEvent(new TaskStatusUpdateEvent.Builder()
+ .taskId(task.getId())
+ .contextId(task.getContextId())
+ .status(new TaskStatus(TaskState.CANCELED))
+ .isFinal(true)
+ .build());
+
+ 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/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/RestApplication.java b/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/RestApplication.java
new file mode 100644
index 0000000..1d9ba6d
--- /dev/null
+++ b/tck/src/main/java/org/wildfly/extras/a2a/server/jakarta/tck/RestApplication.java
@@ -0,0 +1,8 @@
+package org.wildfly.extras.a2a.server.jakarta.tck;
+
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.core.Application;
+
+@ApplicationPath("/")
+public class RestApplication extends Application {
+}
diff --git a/impl/src/main/resources/META-INF/beans.xml b/tck/src/main/resources/META-INF/beans.xml
similarity index 87%
rename from impl/src/main/resources/META-INF/beans.xml
rename to tck/src/main/resources/META-INF/beans.xml
index 9dfae34..9b2940f 100644
--- a/impl/src/main/resources/META-INF/beans.xml
+++ b/tck/src/main/resources/META-INF/beans.xml
@@ -2,5 +2,5 @@
+ bean-discovery-mode="annotated">
\ No newline at end of file
diff --git a/impl/src/main/resources/WEB-INF/web.xml b/tck/src/main/resources/WEB-INF/web.xml
similarity index 100%
rename from impl/src/main/resources/WEB-INF/web.xml
rename to tck/src/main/resources/WEB-INF/web.xml
diff --git a/tck/src/scripts/configure_logger.cli b/tck/src/scripts/configure_logger.cli
new file mode 100644
index 0000000..a45fb24
--- /dev/null
+++ b/tck/src/scripts/configure_logger.cli
@@ -0,0 +1,2 @@
+/subsystem=logging/logger=org.jboss.weld:add(level=DEBUG)
+/subsystem=logging/logger=io.a2a:add(level=DEBUG)
\ No newline at end of file
diff --git a/tests/common/pom.xml b/tests/common/pom.xml
index 240950d..b597a95 100644
--- a/tests/common/pom.xml
+++ b/tests/common/pom.xml
@@ -6,9 +6,8 @@
org.wildfly.extras.a2a
- a2a-java-sdk-server-jakarta-parent
+ a2a-java-sdk-server-jakarta-test-parent
0.2.3.Beta2-SNAPSHOT
- ../../pom.xml
a2a-java-sdk-server-jakarta-test-common
diff --git a/tests/common/src/main/resources/META-INF/beans.xml b/tests/common/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..9b2940f
--- /dev/null
+++ b/tests/common/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,6 @@
+
+
+
\ No newline at end of file
diff --git a/tests/common/src/main/resources/META-INF/services/org.wildfly.extras.a2a.server.apps.jakarta.TestingHook b/tests/common/src/main/resources/META-INF/services/org.wildfly.extras.a2a.server.apps.jakarta.TestingHook
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/common/src/main/resources/WEB-INF/web.xml b/tests/common/src/main/resources/WEB-INF/web.xml
new file mode 100644
index 0000000..4330758
--- /dev/null
+++ b/tests/common/src/main/resources/WEB-INF/web.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/tests/impl/pom.xml b/tests/impl/pom.xml
index c2ba055..8051924 100644
--- a/tests/impl/pom.xml
+++ b/tests/impl/pom.xml
@@ -6,9 +6,8 @@
org.wildfly.extras.a2a
- a2a-java-sdk-server-jakarta-parent
+ a2a-java-sdk-server-jakarta-test-parent
0.2.3.Beta2-SNAPSHOT
- ../../pom.xml
a2a-java-sdk-server-jakarta-tests
diff --git a/tests/impl/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/JakartaA2AServerTest.java b/tests/impl/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/JakartaA2AServerTest.java
index 7313384..d73c1ad 100644
--- a/tests/impl/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/JakartaA2AServerTest.java
+++ b/tests/impl/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/JakartaA2AServerTest.java
@@ -58,7 +58,6 @@ public static WebArchive createTestArchive() throws Exception {
.addPackage(A2ATestResource.class.getPackage())
// Add deployment descriptors
.addAsManifestResource("META-INF/beans.xml", "beans.xml")
- .addAsWebInfResource("META-INF/beans.xml", "beans.xml")
.addAsWebInfResource("WEB-INF/web.xml", "web.xml");
archive.toString(true);
return archive;
diff --git a/tests/pom.xml b/tests/pom.xml
new file mode 100644
index 0000000..458e755
--- /dev/null
+++ b/tests/pom.xml
@@ -0,0 +1,74 @@
+
+
+ 4.0.0
+
+
+ org.wildfly.extras.a2a
+ a2a-java-sdk-server-jakarta-parent
+ 0.2.3.Beta2-SNAPSHOT
+
+
+ a2a-java-sdk-server-jakarta-test-parent
+
+ pom
+
+ WildFly Extras - Java A2A SDK for Jakarta - Test Parent
+ Java SDK for the Agent2Agent Protocol (A2A) - SDK - Jakarta - Test Parent
+
+
+
+
+
+ org.wildfly.glow
+ wildfly-glow-arquillian-plugin
+
+
+
+ org.wildfly
+ wildfly-galleon-pack
+ ${version.wildfly}
+
+
+ standalone.xml
+
+
+
+ scan
+
+ scan
+
+ test-compile
+
+
+
+
+ org.wildfly.plugins
+ wildfly-maven-plugin
+
+ ${project.build.directory}/glow-scan/provisioning.xml
+ ${jboss.home}
+ ${jboss.home}
+
+
+
+
+
+
+
+
+
+
+ test-provisioning
+
+ package
+
+ test-compile
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/wildfly-jar/pom.xml b/tests/wildfly-jar/pom.xml
index 8622be2..6fd6adf 100644
--- a/tests/wildfly-jar/pom.xml
+++ b/tests/wildfly-jar/pom.xml
@@ -6,9 +6,8 @@
org.wildfly.extras.a2a
- a2a-java-sdk-server-jakarta-parent
+ a2a-java-sdk-server-jakarta-test-parent
0.2.3.Beta2-SNAPSHOT
- ../../pom.xml
a2a-java-sdk-server-jakarta-tests-wildfly
diff --git a/tests/wildfly-jar/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/WildFlyJarJakartaA2AServerTest.java b/tests/wildfly-jar/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/WildFlyJarJakartaA2AServerTest.java
index 42cfeed..9145413 100644
--- a/tests/wildfly-jar/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/WildFlyJarJakartaA2AServerTest.java
+++ b/tests/wildfly-jar/src/test/java/org/wildfly/extras/a2a/server/apps/jakarta/WildFlyJarJakartaA2AServerTest.java
@@ -43,7 +43,6 @@ public static WebArchive createTestArchive() throws Exception {
.addPackage(A2ATestResource.class.getPackage())
// Add deployment descriptors
.addAsManifestResource("META-INF/beans.xml", "beans.xml")
- .addAsWebInfResource("META-INF/beans.xml", "beans.xml")
.addAsWebInfResource("WEB-INF/web.xml", "web.xml");
archive.toString(true);
return archive;