diff --git a/.enforcer-scripts/validate-jbang-versions.groovy b/.enforcer-scripts/validate-jbang-versions.groovy deleted file mode 100644 index b8f283319..000000000 --- a/.enforcer-scripts/validate-jbang-versions.groovy +++ /dev/null @@ -1,37 +0,0 @@ -// Fetch the property from the Maven project -def scriptName = project.properties['jbang.script.name'] - -// Fail if the script property is missing -if (scriptName == null) { - throw new IllegalStateException("[ERROR] JBang validator: No jbang.script.name set in properties") -} - -def jbangFile = new File(project.basedir, scriptName) -if (!jbangFile.exists()) { - // If a script name was explicitly provided but doesn't exist, fail. - // If using the fallback, we might want to just skip (return true). - throw new IllegalStateException("[ERROR] JBang validator: File not found: " + jbangFile.absolutePath) -} - -def expectedVersion = project.version -def groupPrefix = "//DEPS io.github.a2asdk:" -def success = true - -jbangFile.eachLine { line -> - if (line.trim().startsWith(groupPrefix)) { - def lastColon = line.lastIndexOf(":") - if (lastColon != -1) { - def actualVersion = line.substring(lastColon + 1).trim().tokenize()[0] - if (actualVersion != expectedVersion) { - System.err.println("[ERROR] JBang Version Mismatch in " + scriptName) - System.err.println(" Expected: " + expectedVersion) - System.err.println(" Found: " + actualVersion + " in line: \"" + line.trim() + "\"") - success = false - } - } - } -} - -if (!success) { - throw new IllegalStateException("[ERROR] JBang version validation failed") -} \ No newline at end of file diff --git a/.github/conventional-commit-lint.yaml b/.github/conventional-commit-lint.yaml new file mode 100644 index 000000000..c967ffa6f --- /dev/null +++ b/.github/conventional-commit-lint.yaml @@ -0,0 +1,2 @@ +enabled: true +always_check_pr_title: true diff --git a/.github/release-please.yml b/.github/release-please.yml new file mode 100644 index 000000000..f411bac3e --- /dev/null +++ b/.github/release-please.yml @@ -0,0 +1,4 @@ +releaseType: maven +handleGHRelease: true +bumpMinorPreMajor: false +bumpPatchForMinorPreMajor: true diff --git a/.github/release-trigger.yml b/.github/release-trigger.yml new file mode 100644 index 000000000..d4ca94189 --- /dev/null +++ b/.github/release-trigger.yml @@ -0,0 +1 @@ +enabled: true diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml deleted file mode 100644 index e2fb7253d..000000000 --- a/.github/workflows/build-and-test.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Build and Test - -on: - # Handle all branches for now - push: - pull_request: - workflow_dispatch: - -# Only run the latest job -concurrency: - group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}' - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - java-version: ['17', '21', '25'] - steps: - - uses: actions/checkout@v4 - - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v4 - with: - java-version: ${{ matrix.java-version }} - distribution: 'temurin' - cache: maven - - name: Build with Maven and run tests - run: mvn -B package --file pom.xml -fae - - name: Upload Test Reports - if: failure() - uses: actions/upload-artifact@v4 - with: - name: surefire-reports-java-${{ matrix.java-version }} - path: | - **/target/surefire-reports/ - **/target/failsafe-reports/ - retention-days: 7 - if-no-files-found: warn - - name: Upload Build Logs - if: failure() - uses: actions/upload-artifact@v4 - with: - name: build-logs-java-${{ matrix.java-version }} - path: | - **/target/*.log - **/target/quarkus.log - retention-days: 3 - if-no-files-found: ignore diff --git a/.github/workflows/build-with-release-profile-run.yml b/.github/workflows/build-with-release-profile-run.yml deleted file mode 100644 index 7da02cf66..000000000 --- a/.github/workflows/build-with-release-profile-run.yml +++ /dev/null @@ -1,144 +0,0 @@ -name: Build with '-Prelease' (Run) - -# Workflow_run job for release profile build verification. -# This workflow has access to secrets and runs the actual build. -# Triggered by build-with-release-profile.yml completion. -# See: https://securitylab.github.com/research/github-actions-preventing-pwn-requests - -on: - workflow_run: - workflows: ["Build with '-Prelease' (Trigger)"] - types: - - completed - -permissions: {} - -jobs: - build: - # Only run for successful trigger workflow from main repository - if: > - ${{ github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.repository.full_name == 'a2aproject/a2a-java' }} - runs-on: ubuntu-latest - permissions: - contents: read - actions: read # Required to download artifacts - statuses: write # Required to report status back to PR - - steps: - - name: Download PR info - uses: actions/download-artifact@v4 - with: - name: pr-info - github-token: ${{ github.token }} - run-id: ${{ github.event.workflow_run.id }} - - - name: Extract PR info - id: pr_info - run: | - if [ -f pr_number ]; then - PR_NUMBER=$(cat pr_number) - echo "pr_number=${PR_NUMBER}" >> $GITHUB_OUTPUT - echo "PR Number: ${PR_NUMBER}" - else - echo "No PR number (push event)" - fi - - PR_SHA=$(cat pr_sha) - echo "pr_sha=${PR_SHA}" >> $GITHUB_OUTPUT - echo "PR SHA: ${PR_SHA}" - - PR_REF=$(cat pr_ref) - echo "pr_ref=${PR_REF}" >> $GITHUB_OUTPUT - echo "PR Ref: ${PR_REF}" - - - name: Report pending status to PR - if: steps.pr_info.outputs.pr_sha - uses: actions/github-script@v7 - with: - script: | - await github.rest.repos.createCommitStatus({ - owner: context.repo.owner, - repo: context.repo.repo, - sha: '${{ steps.pr_info.outputs.pr_sha }}', - state: 'pending', - context: 'Build with -Prelease', - description: 'Building with release profile...', - target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' - }); - - - name: Checkout PR code - uses: actions/checkout@v4 - with: - # Checkout the exact commit from the PR (or push) - # This is safe because the workflow code (this file) is always from main - ref: ${{ steps.pr_info.outputs.pr_sha }} - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - cache: maven - - # Use secrets to import GPG key - - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v6 - with: - gpg_private_key: ${{ secrets.GPG_SIGNING_KEY }} - passphrase: ${{ secrets.GPG_SIGNING_PASSPHRASE }} - - # Create settings.xml for Maven since it needs the 'central-a2asdk-temp' server. - # Populate with username and password from secrets - - name: Create settings.xml - run: | - mkdir -p ~/.m2 - echo "central-a2asdk-temp${{ secrets.CENTRAL_TOKEN_USERNAME }}${{ secrets.CENTRAL_TOKEN_PASSWORD }}" > ~/.m2/settings.xml - - # Build with the same settings as the deploy job - # -s uses the settings file we created. - - name: Build with same arguments as deploy job - run: > - mvn -B install - -s ~/.m2/settings.xml - -P release - -DskipTests - -Drelease.auto.publish=true - env: - # GPG passphrase is set as an environment variable for the gpg plugin to use - GPG_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} - - - name: Build Summary - if: always() - run: | - if [ "${{ job.status }}" = "success" ]; then - echo "✅ Release profile build succeeded" - if [ -n "${{ steps.pr_info.outputs.pr_number }}" ]; then - echo " PR #${{ steps.pr_info.outputs.pr_number }} is ready for release" - fi - else - echo "❌ Release profile build failed" - if [ -n "${{ steps.pr_info.outputs.pr_number }}" ]; then - echo " PR #${{ steps.pr_info.outputs.pr_number }} has release profile issues" - fi - fi - - - name: Report status to PR - if: always() && steps.pr_info.outputs.pr_sha - uses: actions/github-script@v7 - with: - script: | - const state = '${{ job.status }}' === 'success' ? 'success' : 'failure'; - const description = state === 'success' - ? '✅ Release profile build passed' - : '❌ Release profile build failed'; - - await github.rest.repos.createCommitStatus({ - owner: context.repo.owner, - repo: context.repo.repo, - sha: '${{ steps.pr_info.outputs.pr_sha }}', - state: state, - context: 'Build with -Prelease', - description: description, - target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' - }); diff --git a/.github/workflows/build-with-release-profile.yml b/.github/workflows/build-with-release-profile.yml deleted file mode 100644 index 0f4c05687..000000000 --- a/.github/workflows/build-with-release-profile.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Build with '-Prelease' (Trigger) - -# Trigger workflow for release profile build verification. -# This workflow runs on PRs and uploads the PR info for the workflow_run job. -# The actual build with secrets happens in build-with-release-profile-run.yml -# See: https://securitylab.github.com/research/github-actions-preventing-pwn-requests - -on: - pull_request: # Changed from pull_request_target for security - push: - workflow_dispatch: - -# Only run the latest job -concurrency: - group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}' - cancel-in-progress: true - -jobs: - trigger: - # Only run this job for the main repository, not for forks - if: github.repository == 'a2aproject/a2a-java' - runs-on: ubuntu-latest - permissions: - contents: read - - steps: - - name: Prepare PR info - run: | - mkdir -p pr_info - - # Store PR number for workflow_run job - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo ${{ github.event.number }} > pr_info/pr_number - echo ${{ github.event.pull_request.head.sha }} > pr_info/pr_sha - echo ${{ github.event.pull_request.head.ref }} > pr_info/pr_ref - else - # For push events, store the commit sha - echo ${{ github.sha }} > pr_info/pr_sha - echo ${{ github.ref }} > pr_info/pr_ref - fi - - echo "Event: ${{ github.event_name }}" - cat pr_info/* - - - name: Upload PR info - uses: actions/upload-artifact@v4 - with: - name: pr-info - path: pr_info/ - retention-days: 1 diff --git a/.github/workflows/cloud-deployment-example.yml b/.github/workflows/cloud-deployment-example.yml deleted file mode 100644 index 5c4e1e01a..000000000 --- a/.github/workflows/cloud-deployment-example.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: Cloud Deployment Example Test - -on: - push: - pull_request: - workflow_dispatch: - -# Only run the latest job -concurrency: - group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}' - cancel-in-progress: true - -jobs: - test-cloud-deployment: - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up JDK 17 - uses: actions/setup-java@v5 - with: - java-version: '17' - distribution: 'temurin' - cache: maven - - - name: Install Kind - run: | - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 - chmod +x ./kind - sudo mv ./kind /usr/local/bin/kind - kind version - - - name: Build project - run: mvn -B clean install -DskipTests -f pom.xml - - - name: Deploy with Kind - working-directory: examples/cloud-deployment/scripts - run: | - chmod +x deploy.sh - ./deploy.sh --container-tool docker - - - name: Verify deployment - working-directory: examples/cloud-deployment/scripts - run: | - chmod +x verify.sh - ./verify.sh - - - name: Verify agent card is accessible - run: | - echo "Testing agent card endpoint at http://localhost:8080/.well-known/agent-card.json" - curl -f http://localhost:8080/.well-known/agent-card.json || (echo "Agent card not accessible" && exit 1) - - - name: Run test client - working-directory: examples/cloud-deployment/server - run: | - mvn test-compile exec:java \ - -Dexec.mainClass="io.a2a.examples.cloud.A2ACloudExampleClient" \ - -Dexec.classpathScope=test \ - -Dagent.url=http://localhost:8080 \ - -Dci.mode=true - - - name: Show diagnostics on failure - if: failure() - run: | - echo "=== Agent Pod Status ===" - kubectl get pods -n a2a-demo -l app=a2a-agent -o wide - - echo "" - echo "=== Agent Pod Descriptions ===" - for pod in $(kubectl get pods -n a2a-demo -l app=a2a-agent -o jsonpath='{.items[*].metadata.name}'); do - echo "--- Pod: $pod ---" - kubectl describe pod $pod -n a2a-demo | tail -30 - done - - echo "" - echo "=== Recent Events ===" - kubectl get events -n a2a-demo --sort-by='.lastTimestamp' | tail -20 - - echo "" - echo "=== Agent Pod Logs ===" - for pod in $(kubectl get pods -n a2a-demo -l app=a2a-agent -o jsonpath='{.items[*].metadata.name}'); do - echo "--- Logs for $pod ---" - kubectl logs -n a2a-demo $pod --tail=100 || true - done - - echo "" - echo "=== PostgreSQL Logs ===" - kubectl logs -n a2a-demo postgres-0 --tail=50 || true - - echo "" - echo "=== Kafka Logs ===" - kubectl logs -n kafka -l strimzi.io/cluster=a2a-kafka --tail=50 || true - - - name: Cleanup - if: always() - run: | - cd examples/cloud-deployment/scripts - echo "y" | ./cleanup.sh --container-tool docker || true - - diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml deleted file mode 100644 index d23da45d7..000000000 --- a/.github/workflows/conventional-commits.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: "Conventional Commits" - -on: - pull_request: - types: - - opened - - edited - - synchronize - -permissions: - contents: read - -jobs: - main: - permissions: - pull-requests: read - statuses: write - name: Validate PR Title - runs-on: ubuntu-latest - steps: - - name: semantic-pull-request - uses: amannn/action-semantic-pull-request@v5.5.3 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - validateSingleCommit: false diff --git a/.github/workflows/create-github-release.yml b/.github/workflows/create-github-release.yml deleted file mode 100644 index 15baee6c5..000000000 --- a/.github/workflows/create-github-release.yml +++ /dev/null @@ -1,127 +0,0 @@ -name: Create GitHub Release - -on: - push: - tags: - - 'v?[0-9]+.[0-9]+.[0-9]+*' # Trigger on tags like v1.0.0, 1.2.3, v1.2.3.Alpha1 etc. - -jobs: - create-release: - # Only run this job for the main repository, not for forks - if: github.repository == 'a2aproject/a2a-java' - runs-on: ubuntu-latest - permissions: - contents: write # Required to create releases - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Fetch all history for changelog generation - - - name: Extract version from tag - id: version - run: | - # Remove 'v' prefix if present - VERSION=${GITHUB_REF_NAME#v} - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Version: $VERSION" - - - name: Generate release notes - id: release_notes - uses: actions/github-script@v7 - with: - script: | - const version = '${{ steps.version.outputs.version }}'; - - // Get the previous tag - let previousTag = ''; - try { - const { data: tags } = await github.rest.repos.listTags({ - owner: context.repo.owner, - repo: context.repo.repo, - per_page: 100 - }); - - // Find current tag index - const currentIndex = tags.findIndex(tag => tag.name === context.ref.replace('refs/tags/', '')); - - // Get previous tag (next in list) - if (currentIndex >= 0 && currentIndex < tags.length - 1) { - previousTag = tags[currentIndex + 1].name; - } - } catch (error) { - console.log('Could not fetch previous tag:', error.message); - } - - // Build release notes - let releaseNotes = `## A2A Java SDK ${version}\n\n`; - - // Add Maven Central installation instructions - releaseNotes += `### Installation\n\n`; - releaseNotes += `**Maven**:\n\`\`\`xml\n\n`; - releaseNotes += ` io.github.a2asdk\n`; - releaseNotes += ` a2a-java-sdk-client\n`; - releaseNotes += ` ${version}\n`; - releaseNotes += `\n\`\`\`\n\n`; - - releaseNotes += `**Gradle**:\n\`\`\`gradle\n`; - releaseNotes += `implementation 'io.github.a2asdk:a2a-java-sdk-client:${version}'\n`; - releaseNotes += `\`\`\`\n\n`; - - // Add links - releaseNotes += `### Links\n\n`; - releaseNotes += `- [Maven Central](https://central.sonatype.com/artifact/io.github.a2asdk/a2a-java-sdk-parent/${version})\n`; - releaseNotes += `- [JavaDoc](https://javadoc.io/doc/io.github.a2asdk/a2a-java-sdk-parent/${version})\n`; - releaseNotes += `- [GitHub](https://github.com/a2aproject/a2a-java/tree/v${version})\n\n`; - - // Add changelog header - if (previousTag) { - releaseNotes += `### Changes since ${previousTag}\n\n`; - releaseNotes += `[Full Changelog](https://github.com/a2aproject/a2a-java/compare/${previousTag}...v${version})\n\n`; - } else { - releaseNotes += `### Changes\n\n`; - } - - return releaseNotes; - - - name: Create GitHub Release - uses: actions/github-script@v7 - with: - script: | - const version = '${{ steps.version.outputs.version }}'; - const tag = context.ref.replace('refs/tags/', ''); - const releaseNotes = ${{ steps.release_notes.outputs.result }}; - - // Determine if this is a pre-release - const isPrerelease = version.includes('Alpha') || - version.includes('Beta') || - version.includes('RC') || - version.includes('SNAPSHOT'); - - try { - const { data: release } = await github.rest.repos.createRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: tag, - name: `v${version}`, - body: releaseNotes, - draft: false, - prerelease: isPrerelease, - generate_release_notes: true // GitHub will append auto-generated notes - }); - - console.log(`✅ Created release: ${release.html_url}`); - core.summary - .addHeading(`Release v${version} Created`) - .addLink('View Release', release.html_url) - .addLink('Maven Central', `https://central.sonatype.com/artifact/io.github.a2asdk/a2a-java-sdk-parent/${version}`) - .write(); - - } catch (error) { - if (error.status === 422 && error.message.includes('already_exists')) { - console.log('⚠️ Release already exists for this tag'); - } else { - throw error; - } - } diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml deleted file mode 100644 index a38b0f7be..000000000 --- a/.github/workflows/release-please.yml +++ /dev/null @@ -1,19 +0,0 @@ -on: - push: - branches: - - main - -permissions: - contents: write - pull-requests: write - -name: release-please - -jobs: - release-please: - runs-on: ubuntu-latest - steps: - - uses: googleapis/release-please-action@v4 - with: - token: ${{ secrets.A2A_BOT_PAT }} - release-type: java diff --git a/.github/workflows/release-to-maven-central.yml b/.github/workflows/release-to-maven-central.yml deleted file mode 100644 index c0f5a9724..000000000 --- a/.github/workflows/release-to-maven-central.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Publish release to Maven Central - -on: - push: - tags: - - 'v?[0-9]+.[0-9]+.[0-9]+*' # Trigger on tags like v1.0.0, 1.2.3, v1.2.3.Alpha1 etc. - -jobs: - publish: - # Only run this job for the main repository, not for forks - if: github.repository == 'a2aproject/a2a-java' - runs-on: ubuntu-latest - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - cache: maven - - # Use secrets to import GPG key - - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v6 - with: - gpg_private_key: ${{ secrets.GPG_SIGNING_KEY }} - passphrase: ${{ secrets.GPG_SIGNING_PASSPHRASE }} - - # Create settings.xml for Maven since it needs the 'central-a2asdk-temp' server. - # Populate wqith username and password from secrets - - name: Create settings.xml - run: | - mkdir -p ~/.m2 - echo "central-a2asdk-temp${{ secrets.CENTRAL_TOKEN_USERNAME }}${{ secrets.CENTRAL_TOKEN_PASSWORD }}" > ~/.m2/settings.xml - - # Deploy to Maven Central - # -s uses the settings file we created. - - name: Publish to Maven Central - run: > - mvn -B deploy - -s ~/.m2/settings.xml - -P release - -DskipTests - -Drelease.auto.publish=true - env: - # GPG passphrase is set as an environment variable for the gpg plugin to use - GPG_PASSPHRASE: ${{ secrets.GPG_SIGNING_PASSPHRASE }} diff --git a/.github/workflows/run-tck.yml b/.github/workflows/run-tck.yml deleted file mode 100644 index 75ed7819f..000000000 --- a/.github/workflows/run-tck.yml +++ /dev/null @@ -1,175 +0,0 @@ -name: Run TCK - -on: - # Handle all branches for now - push: - branches: - - main - pull_request: - branches: - - main - workflow_dispatch: - -env: - # Tag/branch of the TCK - TCK_VERSION: main - # Tell the TCK runner to report failure if the quality tests fail - A2A_TCK_FAIL_ON_QUALITY: 1 - # Tell the TCK runner to report failure if the features tests fail - A2A_TCK_FAIL_ON_FEATURES: 1 - # Tells uv to not need a venv, and instead use system - UV_SYSTEM_PYTHON: 1 - # SUT_JSONRPC_URL to use for the TCK and the server agent - SUT_JSONRPC_URL: http://localhost:9999 - # Slow system on CI - TCK_STREAMING_TIMEOUT: 5.0 - -# Only run the latest job -concurrency: - group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}' - cancel-in-progress: true - -jobs: - tck-test: - runs-on: ubuntu-latest - strategy: - matrix: - java-version: [17, 21, 25] - steps: - - name: Checkout a2a-java - uses: actions/checkout@v4 - - name: Checkout a2a-tck - uses: actions/checkout@v4 - with: - repository: a2aproject/a2a-tck - path: tck/a2a-tck - ref: ${{ env.TCK_VERSION }} - - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v5 - with: - java-version: ${{ matrix.java-version }} - distribution: 'temurin' - cache: maven - - name: check java_home - run: echo $JAVA_HOME - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version-file: "tck/a2a-tck/pyproject.toml" - - name: Install uv and Python dependencies - run: | - pip install uv - uv pip install -e . - working-directory: tck/a2a-tck - - name: Build with Maven, skipping tests - run: mvn -B install -DskipTests - - name: Start SUT - run: SUT_GRPC_URL=${{ env.SUT_JSONRPC_URL }} SUT_REST_URL=${{ env.SUT_JSONRPC_URL }} mvn -B quarkus:dev & #SUT_JSONRPC_URL already set - working-directory: tck - - name: Wait for SUT to start - run: | - URL="${{ env.SUT_JSONRPC_URL }}/.well-known/agent-card.json" - EXPECTED_STATUS=200 - TIMEOUT=120 - RETRY_INTERVAL=2 - START_TIME=$(date +%s) - - while true; do - # Calculate elapsed time - CURRENT_TIME=$(date +%s) - ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) - - # Check for timeout - if [ "$ELAPSED_TIME" -ge "$TIMEOUT" ]; then - echo "❌ Timeout: Server did not respond with status $EXPECTED_STATUS within $TIMEOUT seconds." - exit 1 - fi - - # Get HTTP status code. || true is to reporting a failure to connect as an error - HTTP_STATUS=$(curl --output /dev/null --silent --write-out "%{http_code}" "$URL") || true - echo "STATUS: ${HTTP_STATUS}" - - # Check if we got the correct status code - if [ "$HTTP_STATUS" -eq "$EXPECTED_STATUS" ]; then - echo "✅ Server is up! Received status $HTTP_STATUS after $ELAPSED_TIME seconds." - break; - fi - - # Wait before retrying - echo "⏳ Server not ready (status: $HTTP_STATUS). Retrying in $RETRY_INTERVAL seconds..." - sleep "$RETRY_INTERVAL" - done - - - name: Run TCK - id: run-tck - timeout-minutes: 5 - run: | - set -o pipefail - ./run_tck.py --sut-url ${{ env.SUT_JSONRPC_URL }} --category all --transports jsonrpc,grpc,rest --compliance-report report.json 2>&1 | tee tck-output.log - working-directory: tck/a2a-tck - - name: Capture Diagnostics on Failure - if: failure() - run: | - echo "=== Capturing diagnostic information ===" - - # Create diagnostics directory - mkdir -p tck/target/diagnostics - - # Capture process list - echo "📋 Capturing process list..." - ps auxww > tck/target/diagnostics/processes.txt - - # Find the actual Quarkus JVM (child of Maven process), not the Maven parent - # Look for the dev.jar process which is the actual application - QUARKUS_PID=$(pgrep -f "a2a-tck-server-dev.jar" || echo "") - if [ -n "$QUARKUS_PID" ]; then - echo "📊 Capturing thread dump for Quarkus JVM PID $QUARKUS_PID" - jstack $QUARKUS_PID > tck/target/diagnostics/thread-dump.txt || echo "Failed to capture thread dump" - if [ -f tck/target/diagnostics/thread-dump.txt ]; then - echo "✅ Thread dump captured ($(wc -l < tck/target/diagnostics/thread-dump.txt) lines)" - fi - else - echo "⚠️ No Quarkus JVM process found for thread dump" - echo "Available Java processes:" - ps aux | grep java | tee -a tck/target/diagnostics/processes.txt || true - fi - - # Capture Quarkus application logs (if available) - echo "📝 Checking for Quarkus logs..." - if [ -f tck/target/quarkus.log ]; then - cp tck/target/quarkus.log tck/target/diagnostics/ - echo "✅ Copied quarkus.log ($(wc -l < tck/target/quarkus.log) lines)" - fi - - # Copy TCK server logs - if [ -f tck/target/tck-test.log ]; then - cp tck/target/tck-test.log tck/target/diagnostics/ - echo "✅ Copied tck-test.log ($(wc -l < tck/target/tck-test.log) lines)" - fi - - echo "" - echo "=== Diagnostic capture complete ===" - - name: Stop Quarkus Server - if: always() - run: | - # Find and kill the Quarkus process to ensure logs are flushed - pkill -f "quarkus:dev" || true - sleep 2 - - name: Upload TCK Diagnostics - if: failure() - uses: actions/upload-artifact@v4 - with: - name: tck-diagnostics-java-${{ matrix.java-version }} - path: | - tck/target/diagnostics/ - tck/a2a-tck/tck-output.log - retention-days: 7 - if-no-files-found: warn - - name: Upload TCK Compliance Report - if: always() - uses: actions/upload-artifact@v4 - with: - name: tck-compliance-report-java-${{ matrix.java-version }} - path: tck/a2a-tck/report.json - retention-days: 14 - if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index 3679c8f0c..91a800a18 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,6 @@ pom.xml.releaseBackup pom.xml.versionsBackup release.properties .flattened-pom.xml -*.args - -#Claude -CLAUDE.md # Eclipse .project @@ -22,10 +18,8 @@ bin/ *.iml *.iws -# Apache NetBeans +# NetBeans nb-configuration.xml -nbactions.xml -nbproject/ # Visual Studio Code .vscode @@ -49,9 +43,3 @@ nbproject/ /.quarkus/cli/plugins/ # TLS Certificates .certs/ - -# Private Claude config -.claude/ -.serena/ -.bob/ -claudedocs diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 4eb10e60b..000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,136 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or advances of - any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, - without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement: - -Farah Juma - fjuma@redhat.com \ -Kabir Khan - kkhan@redhat.com \ -Stefano Maestri - smaestri@redhat.com - -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. - -For answers to common questions about this code of conduct, see the FAQ at -[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at -[https://www.contributor-covenant.org/translations][translations]. - -[homepage]: https://www.contributor-covenant.org -[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html -[Mozilla CoC]: https://github.com/mozilla/diversity -[FAQ]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations diff --git a/COMMUNITY_ARTICLES.md b/COMMUNITY_ARTICLES.md deleted file mode 100644 index 65f3b70a4..000000000 --- a/COMMUNITY_ARTICLES.md +++ /dev/null @@ -1,32 +0,0 @@ -# Community Articles - -Here are some articles and videos from the community that you may find helpful. - -## General Agent and A2A Introduction - -* [Agents are not tools](https://www.googlecloudcommunity.com/gc/Community-Blogs/Agents-are-not-tools/ba-p/922716): A nice explanation of what agents are from one of the main contributors of A2A spec. -* [Introducing A2A](https://goo.gle/a2a-video): A good video introducing A2A. - -## A2A Java SDK - -* [Quarkus and WildFly teams from Red Hat collaborating with Google on launch of Agent2Agent Java SDK](https://quarkus.io/blog/a2a-project-launches-java-sdk/): Announcing the new availability of the A2A Java SDK and giving a quick introduction to it. This article also appeared in the [Medium Google Cloud publication](https://medium.com/google-cloud/quarkus-and-wildfly-teams-from-red-hat-collaborating-with-google-on-launch-of-agent2agent-java-sdk-5f8cc64921cb). - -* [A2A Java SDK Introduction Video](https://www.youtube.com/watch?v=5CZzW-wvEQs): A great video introducing the A2A Java SDK and giving a walkthrough of a multi-language interoperability example. - -* [Getting Started with Quarkus and A2A Java SDK](https://quarkus.io/blog/quarkus-and-a2a-java-sdk/): An introduction on how to easily get started with Quarkus and the A2A Java SDK. This article also appeared in the [Medium Google Cloud publication](https://medium.com/google-cloud/getting-started-with-quarkus-and-the-a2a-java-sdk-c8b1529c8445). - -* [Getting Started with Quarkus and A2A Java SDK 0.3.0](https://quarkus.io/blog/quarkus-a2a-java-0-3-0-alpha-release/): Learn about what's new in the 0.3.0 version of the A2A Java SDK. This article also appeared in the [Medium Google Cloud publication](https://medium.com/google-cloud/getting-started-with-quarkus-and-a2a-java-sdk-0-3-0-c4e70620a805). - -* [A2A Java SDK: Support for the REST Transport is Now Here](https://quarkus.io/blog/quarkus-a2a-java-0-3-0-beta-release/): Learn about the new support for the REST transport introduced in A2A Java SDK 0.3.0.Beta1. This article also appeared in the [Medium Google Cloud publication](https://medium.com/google-cloud/a2a-java-sdk-support-for-the-rest-transport-is-now-here-56c666060b32). - -* [Multi-Language Agent Collaboration and Interoperability with A2A](https://medium.com/google-cloud/multi-language-agent-collaboration-and-interoperability-with-a2a-e5fe80b4962d): A deep dive into a multi-language, multi-agent sample where agents written in Java, Python, and TypeScript work together to achieve a common goal: content creation. - -* [Getting Started with A2A Java SDK and gRPC](https://quarkus.io/blog/quarkus-a2a-java-grpc/): Let's learn how to create an A2A server agent and an A2A client that can communicate using the gRPC transport. This article also appeared in the [Medium Google Cloud publication](https://medium.com/google-cloud/getting-started-with-the-a2a-java-sdk-and-grpc-11c987df73c1). - -* [How to Secure Your A2A Server Agent with Keycloak OAuth2](https://quarkus.io/blog/quarkus-a2a-java-security/): This blog post shows how to secure an A2A server agent using OAuth2 bearer tokens via Keycloak and shows how to enable an A2A client to automatically obtain and pass the required token in each request. - -## A2A Java SDK for Jakarta Servers - -* [Building your First A2A Agent](https://www.wildfly.org/news/2025/08/07/Building-your-First-A2A-Agent/): An introduction on how to use the A2A Java SDK for Jakarta Servers with WildFly. - - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 0b92171d8..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,91 +0,0 @@ -Contributing to a2a-java -================================== - -Welcome to the A2A Java SDK project! We welcome contributions from the community. This guide will walk you through the steps for getting started on our project. - -- [Forking the Project](#forking-the-project) -- [Issues](#issues) - - [Good First Issues](#good-first-issues) -- [Setting up your Developer Environment](#setting-up-your-developer-environment) -- [Contributing Guidelines](#contributing-guidelines) -- [Community](#community) - - -## Forking the Project -To contribute, you will first need to fork the [a2a-java](https://github.com/a2aproject/a2a-java) repository. - -This can be done by looking in the top-right corner of the repository page and clicking "Fork". -![fork](images/fork.jpg) - -The next step is to clone your newly forked repository onto your local workspace. This can be done by going to your newly forked repository, which should be at `https://github.com/USERNAME/a2a-java`. - -Then, there will be a green button that says "Code". Click on it and copy the URL. - -Then, in your terminal, paste the following command: -```bash -git clone [URL] -``` -Be sure to replace [URL] with the URL that you copied. - -Now you have the repository on your computer! - -## Issues -The `a2a-java` project uses GitHub to manage issues. All issues can be found [here](https://github.com/a2aproject/a2a-java/issues). - -To create a new issue, comment on an existing issue, or assign an issue to yourself, you'll need to first [create a GitHub account](https://github.com/). - - -### Good First Issues -Want to contribute to the a2a-java project but aren't quite sure where to start? Check out our issues with the `good-first-issue` label. These are a triaged set of issues that are great for getting started on our project. These can be found [here](https://github.com/a2aproject/a2a-java/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22). - -Once you have selected an issue you'd like to work on, make sure it's not already assigned to someone else, and assign it to yourself. - -It is recommended that you use a separate branch for every issue you work on. To keep things straightforward and memorable, you can name each branch using the GitHub issue number. This way, you can have multiple PRs open for different issues. For example, if you were working on [issue-20](https://github.com/a2aproject/a2a-java/issues/20), you could use `issue-20` as your branch name. - -## Setting up your Developer Environment -You will need: - -* Java 17+ -* Git -* An IDE (e.g., IntelliJ IDEA, Eclipse, VSCode, etc.) - -To set up your development environment you need to: - -1. First `cd` to the directory where you cloned the project (eg: `cd a2a-java`) - -2. Add a remote ref to upstream, for pulling future updates. For example: - - ``` - git remote add upstream https://github.com/a2aproject/a2a-java - ``` - -3. To build `a2a-java` and run the tests, use the following command: - - ``` - mvn clean install - ``` - -4. To skip the tests: - - ``` - mvn clean install -DskipTests=true - ``` - -## Contributing Guidelines - -When submitting a PR, please keep the following guidelines in mind: - -1. In general, it's good practice to squash all of your commits into a single commit. For larger changes, it's ok to have multiple meaningful commits. If you need help with squashing your commits, feel free to ask us how to do this on your pull request. We're more than happy to help! - -2. Please link the issue you worked on in the description of your pull request and in your commit message. For example, for issue-20, the PR description and commit message could be: ```Add tests to A2AClientTest for sending a task with a FilePart and with a DataPart - Fixes #20``` - -3. Your PR should include tests for the functionality that you are adding. - -4. Your PR should include appropriate [documentation](https://github.com/a2aproject/a2a-java/blob/main/README.md) for the functionality that you are adding. - -## Code Reviews - -All submissions, including submissions by project members, need to be reviewed by at least one `a2a-java` committer before being merged. - -The [GitHub Pull Request Review Process](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews) is followed for every pull request. diff --git a/CONTRIBUTING_INTEGRATIONS.md b/CONTRIBUTING_INTEGRATIONS.md deleted file mode 100644 index 9fc06a520..000000000 --- a/CONTRIBUTING_INTEGRATIONS.md +++ /dev/null @@ -1,15 +0,0 @@ -# Contributing A2A SDK Integrations - -To add your A2A SDK Integration for your chosen runtime to the list of integrations in the [README](README.md#server-integrations), open a pull request adding it to the list. - -The pull request should contain a link to your project page. - -Then the project page itself needs to contain the following information as a minimum: - -* How to use the integration. - * Ideally there should be a sample demonstrating how to use it -* The integration should have tests, extending [AbstractA2AServerTest](tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java) -* The integration should pass the [TCK](https://github.com/a2aproject/a2a-tck), and make it obvious how to see that it has passed. -* Ideally, the integration should be deployed in Maven Central. If that is not possible, provide clear instructions for how to build it. - -If some of the above points are problematic, feel free to point that out in your pull request, and we can discuss further. For example, AbstractA2AServerTest is currently written with only the initial runtimes in mind, and might need some tweaking. \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 7a4a3ea24..000000000 --- a/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 48d28a8cd..000000000 --- a/README.md +++ /dev/null @@ -1,684 +0,0 @@ -# A2A Java SDK - -[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE) - - - - -

- A2A Logo -

-

A Java library that helps run agentic applications as A2AServers following the Agent2Agent (A2A) Protocol.

- - -## Installation - -You can build the A2A Java SDK using `mvn`: - -```bash -mvn clean install -``` - -### Regeneration of gRPC files -We copy https://github.com/a2aproject/A2A/blob/main/specification/grpc/a2a.proto to the [`spec-grpc/`](./spec-grpc) project, and adjust the `java_package` option to be as follows: -``` -option java_package = "io.a2a.grpc"; -``` -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. - -## Examples - -You can find examples of how to use the A2A Java SDK in the [a2a-samples repository](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents). - -More examples will be added soon. - -## A2A Server - -The A2A Java SDK provides a Java server implementation of the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/). To run your agentic Java application as an A2A server, simply follow the steps below. - -- [Add an A2A Java SDK Server Maven dependency to your project](#1-add-an-a2a-java-sdk-server-maven-dependency-to-your-project) -- [Add a class that creates an A2A Agent Card](#2-add-a-class-that-creates-an-a2a-agent-card) -- [Add a class that creates an A2A Agent Executor](#3-add-a-class-that-creates-an-a2a-agent-executor) - -### 1. Add an A2A Java SDK Server Maven dependency to your project - -Adding a dependency on an A2A Java SDK Server will provide access to the core classes -that make up the A2A specification and allow you to run your agentic Java application as an A2A server agent. - -The A2A Java SDK provides [reference A2A server implementations](reference) based on [Quarkus](https://quarkus.io) for use with our tests and examples. However, the project is designed in such a way that it is trivial to integrate with various Java runtimes. - -[Server Integrations](#server-integrations) contains a list of community contributed integrations of the server with various runtimes. You might be able to use one of these for your target runtime, or you can use them as inspiration to create your own. - -#### Server Transports -The A2A Java SDK Reference Server implementations support the following transports: - -* JSON-RPC 2.0 -* gRPC -* HTTP+JSON/REST - -To use the reference implementation with the JSON-RPC protocol, add the following dependency to your project: - -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* - -```xml - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - ${io.a2a.sdk.version} - -``` - -To use the reference implementation with the gRPC protocol, add the following dependency to your project: - -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* - -```xml - - io.github.a2asdk - a2a-java-sdk-reference-grpc - - ${io.a2a.sdk.version} - -``` - -To use the reference implementation with the HTTP+JSON/REST protocol, add the following dependency to your project: - -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* - -```xml - - io.github.a2asdk - a2a-java-sdk-reference-rest - - ${io.a2a.sdk.version} - -``` - -Note that you can add more than one of the above dependencies to your project depending on the transports -you'd like to support. - -### 2. Add a class that creates an A2A Agent Card - -```java -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentSkill; -... - -@ApplicationScoped -public class WeatherAgentCardProducer { - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return AgentCard.builder() - .name("Weather Agent") - .description("Helps with weather") - .url("http://localhost:10001") - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(AgentSkill.builder() - .id("weather_search") - .name("Search weather") - .description("Helps with weather in cities or states") - .tags(Collections.singletonList("weather")) - .examples(List.of("weather in LA, CA")) - .build())) - .protocolVersion(io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION) - .build(); - } -} -``` - -### 3. Add a class that creates an A2A Agent Executor - -```java -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.JSONRPCError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; -... - -@ApplicationScoped -public class WeatherAgentExecutorProducer { - - @Inject - WeatherAgent weatherAgent; - - @Produces - public AgentExecutor agentExecutor() { - return new WeatherAgentExecutor(weatherAgent); - } - - private static class WeatherAgentExecutor implements AgentExecutor { - - private final WeatherAgent weatherAgent; - - public WeatherAgentExecutor(WeatherAgent weatherAgent) { - this.weatherAgent = weatherAgent; - } - - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { - // mark the task as submitted and start working on it - if (context.getTask() == null) { - agentEmitter.submit(); - } - agentEmitter.startWork(); - - // extract the text from the message - String userMessage = extractTextFromMessage(context.getMessage()); - - // call the weather agent with the user's message - String response = weatherAgent.chat(userMessage); - - // create the response part - TextPart responsePart = new TextPart(response); - List> parts = List.of(responsePart); - - // add the response as an artifact and complete the task - agentEmitter.addArtifact(parts); - agentEmitter.complete(); - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { - Task task = context.getTask(); - - if (task.getStatus().state() == TaskState.CANCELED) { - // task already cancelled - throw new TaskNotCancelableError(); - } - - if (task.getStatus().state() == TaskState.COMPLETED) { - // task already completed - throw new TaskNotCancelableError(); - } - - // cancel the task - agentEmitter.cancel(); - } - - private String extractTextFromMessage(Message message) { - StringBuilder textBuilder = new StringBuilder(); - if (message.getParts() != null) { - for (Part part : message.getParts()) { - if (part instanceof TextPart textPart) { - textBuilder.append(textPart.getText()); - } - } - } - return textBuilder.toString(); - } - } -} -``` - -### 4. Configuration System - -The A2A Java SDK uses a flexible configuration system that works across different frameworks. - -**Default behavior:** Configuration values come from `META-INF/a2a-defaults.properties` files on the classpath (provided by core modules and extras). These defaults work out of the box without any additional setup. - -**Customizing configuration:** -- **Quarkus/MicroProfile Config users**: Add the [`microprofile-config`](integrations/microprofile-config/README.md) integration to override defaults via `application.properties`, environment variables, or system properties -- **Spring/other frameworks**: See the [integration module README](integrations/microprofile-config/README.md#custom-config-providers) for how to implement a custom `A2AConfigProvider` -- **Reference implementations**: Already include the MicroProfile Config integration - -#### Configuration Properties - -**Executor Settings** (Optional) - -The SDK uses a dedicated executor for async operations like streaming. Default: 5 core threads, 50 max threads. - -```properties -# Core thread pool size for the @Internal executor (default: 5) -a2a.executor.core-pool-size=5 - -# Maximum thread pool size (default: 50) -a2a.executor.max-pool-size=50 - -# Thread keep-alive time in seconds (default: 60) -a2a.executor.keep-alive-seconds=60 -``` - -**Blocking Call Timeouts** (Optional) - -```properties -# Timeout for agent execution in blocking calls (default: 30 seconds) -a2a.blocking.agent.timeout.seconds=30 - -# Timeout for event consumption in blocking calls (default: 5 seconds) -a2a.blocking.consumption.timeout.seconds=5 -``` - -**Why this matters:** -- **Streaming Performance**: The executor handles streaming subscriptions. Too few threads can cause timeouts under concurrent load. -- **Resource Management**: The dedicated executor prevents streaming operations from competing with the ForkJoinPool. -- **Concurrency**: In production with high concurrent streaming, increase pool sizes accordingly. -- **Agent Timeouts**: LLM-based agents may need longer timeouts (60-120s) compared to simple agents. - -**Note:** The reference server implementations (Quarkus-based) automatically include the MicroProfile Config integration, so properties work out of the box in `application.properties`. - -## A2A Client - -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: - -* JSON-RPC 2.0 -* gRPC -* HTTP+JSON/REST - -To make use of the Java `Client`: - -### 1. Add the A2A Java SDK Client dependency to your project - -Adding a dependency on `a2a-java-sdk-client` will provide access to a `ClientBuilder` -that you can use to create your A2A `Client`. - ----- -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* ----- - -```xml - - io.github.a2asdk - a2a-java-sdk-client - - ${io.a2a.sdk.version} - -``` - -### 2. Add one or more dependencies on the A2A Java SDK Client Transport(s) you'd like to use - -By default, the `sdk-client` artifact includes the JSONRPC transport dependency. However, you must still explicitly configure this transport when building the `Client` as described in the [JSON-RPC Transport section](#json-rpc-transport-configuration). - - -If you want to use the gRPC transport, you'll need to add a relevant dependency: - ----- -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* ----- - -```xml - - io.github.a2asdk - a2a-java-sdk-client-transport-grpc - - ${io.a2a.sdk.version} - -``` - - -If you want to use the HTTP+JSON/REST transport, you'll need to add a relevant dependency: - ----- -> *⚠️ The `io.github.a2asdk` `groupId` below is temporary and will likely change for future releases.* ----- - -```xml - - io.github.a2asdk - a2a-java-sdk-client-transport-rest - - ${io.a2a.sdk.version} - -``` - -### Sample Usage - -#### Create a Client using the ClientBuilder - -```java -// First, get the agent card for the A2A server agent you want to connect to -AgentCard agentCard = new A2ACardResolver("http://localhost:1234").getAgentCard(); - -// Specify configuration for the ClientBuilder -ClientConfig clientConfig = new ClientConfig.Builder() - .setAcceptedOutputModes(List.of("text")) - .build(); - -// Create event consumers to handle responses that will be received from the A2A server -// (these consumers will be used for both streaming and non-streaming responses) -List> consumers = List.of( - (event, card) -> { - if (event instanceof MessageEvent messageEvent) { - // handle the messageEvent.getMessage() - ... - } else if (event instanceof TaskEvent taskEvent) { - // handle the taskEvent.getTask() - ... - } else if (event instanceof TaskUpdateEvent updateEvent) { - // handle the updateEvent.getTask() - ... - } - } -); - -// Create a handler that will be used for any errors that occur during streaming -Consumer errorHandler = error -> { - // handle the error.getMessage() - ... -}; - -// Create the client using the builder -Client client = Client - .builder(agentCard) - .clientConfig(clientConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) - .addConsumers(consumers) - .streamingErrorHandler(errorHandler) - .build(); -``` - -#### Configuring Transport-Specific Settings - -Different transport protocols can be configured with specific settings using specific `ClientTransportConfig` implementations. The A2A Java SDK provides `JSONRPCTransportConfig` for the JSON-RPC transport and `GrpcTransportConfig` for the gRPC transport. - -##### JSON-RPC Transport Configuration - -For the JSON-RPC transport, to use the default `JdkA2AHttpClient`, provide a `JSONRPCTransportConfig` created with its default constructor. - -To use a custom HTTP client implementation, simply create a `JSONRPCTransportConfig` as follows: - -```java -// Create a custom HTTP client -A2AHttpClient customHttpClient = ... - -// Configure the client settings -ClientConfig clientConfig = new ClientConfig.Builder() - .setAcceptedOutputModes(List.of("text")) - .build(); - -Client client = Client - .builder(agentCard) - .clientConfig(clientConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig(customHttpClient)) - .build(); -``` - -##### gRPC Transport Configuration - -For the gRPC transport, you must configure a channel factory: - -```java -// Create a channel factory function that takes the agent URL and returns a Channel -Function channelFactory = agentUrl -> { - return ManagedChannelBuilder.forTarget(agentUrl) - ... - .build(); -}; - -// Configure the client with transport-specific settings -ClientConfig clientConfig = new ClientConfig.Builder() - .setAcceptedOutputModes(List.of("text")) - .build(); - -Client client = Client - .builder(agentCard) - .clientConfig(clientConfig) - .withTransport(GrpcTransport.class, new GrpcTransportConfig(channelFactory)) - .build(); -``` - - -##### HTTP+JSON/REST Transport Configuration - -For the HTTP+JSON/REST transport, if you'd like to use the default `JdkA2AHttpClient`, provide a `RestTransportConfig` created with its default constructor. - -To use a custom HTTP client implementation, simply create a `RestTransportConfig` as follows: - -```java -// Create a custom HTTP client -A2AHttpClient customHttpClient = ... - -// Configure the client settings -ClientConfig clientConfig = new ClientConfig.Builder() - .setAcceptedOutputModes(List.of("text")) - .build(); - -Client client = Client - .builder(agentCard) - .clientConfig(clientConfig) - .withTransport(RestTransport.class, new RestTransportConfig(customHttpClient)) - .build(); -``` - -##### Multiple Transport Configurations - -You can specify configuration for multiple transports, the appropriate configuration -will be used based on the selected transport: - -```java -// Configure both JSON-RPC and gRPC transports -Client client = Client - .builder(agentCard) - .withTransport(GrpcTransport.class, new GrpcTransportConfig(channelFactory)) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) - .withTransport(RestTransport.class, new RestTransportConfig()) - .build(); -``` - -#### Send a message to the A2A server agent - -```java -// Send a text message to the A2A server agent -Message message = A2A.toUserMessage("tell me a joke"); - -// Send the message (uses configured consumers to handle responses) -// Streaming will automatically be used if supported by both client and server, -// otherwise the non-streaming send message method will be used automatically -client.sendMessage(message); - -// You can also optionally specify a ClientCallContext with call-specific config to use -client.sendMessage(message, clientCallContext); -``` - -#### Send a message with custom event handling - -```java -// Create custom consumers for this specific message -List> customConsumers = List.of( - (event, card) -> { - // handle this specific message's responses - ... - } -); - -// Create custom error handler -Consumer customErrorHandler = error -> { - // handle the error - ... -}; - -Message message = A2A.toUserMessage("tell me a joke"); -client.sendMessage(message, customConsumers, customErrorHandler); -``` - -#### Get the current state of a task - -```java -// Retrieve the task with id "task-1234" -Task task = client.getTask(new TaskQueryParams("task-1234")); - -// You can also specify the maximum number of history items for the task -// to include in the response -Task task = client.getTask(new TaskQueryParams("task-1234", 10)); - -// You can also optionally specify a ClientCallContext with call-specific config to use -Task task = client.getTask(new TaskQueryParams("task-1234"), clientCallContext); -``` - -#### Cancel an ongoing task - -```java -// Cancel the task we previously submitted with id "task-1234" -Task cancelledTask = client.cancelTask(new TaskIdParams("task-1234")); - -// You can also specify additional properties using a map -Map metadata = Map.of("reason", "user_requested"); -Task cancelledTask = client.cancelTask(new TaskIdParams("task-1234", metadata)); - -// You can also optionally specify a ClientCallContext with call-specific config to use -Task cancelledTask = client.cancelTask(new TaskIdParams("task-1234"), clientCallContext); -``` - -#### Get a push notification configuration for a task - -```java -// Get task push notification configuration -TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams("task-1234")); - -// The push notification configuration ID can also be optionally specified -TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams("task-1234", "config-4567")); - -// Additional properties can be specified using a map -Map metadata = Map.of("source", "client"); -TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams("task-1234", "config-1234", metadata)); - -// You can also optionally specify a ClientCallContext with call-specific config to use -TaskPushNotificationConfig config = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams("task-1234"), clientCallContext); -``` - -#### Set a push notification configuration for a task - -```java -// Set task push notification configuration -PushNotificationConfig pushNotificationConfig = PushNotificationConfig.builder() - .url("https://example.com/callback") - .authenticationInfo(new AuthenticationInfo(Collections.singletonList("jwt"), null)) - .build(); - -TaskPushNotificationConfig taskConfig = TaskPushNotificationConfig.builder() - .taskId("task-1234") - .pushNotificationConfig(pushNotificationConfig) - .build(); - -TaskPushNotificationConfig result = client.createTaskPushNotificationConfiguration(taskConfig); - -// You can also optionally specify a ClientCallContext with call-specific config to use -TaskPushNotificationConfig result = client.createTaskPushNotificationConfiguration(taskConfig, clientCallContext); -``` - -#### List the push notification configurations for a task - -```java -List configs = client.listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams("task-1234")); - -// Additional properties can be specified using a map -Map metadata = Map.of("filter", "active"); -List configs = client.listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams("task-1234", metadata)); - -// You can also optionally specify a ClientCallContext with call-specific config to use -List configs = client.listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams("task-1234"), clientCallContext); -``` - -#### Delete a push notification configuration for a task - -```java -client.deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567")); - -// Additional properties can be specified using a map -Map metadata = Map.of("reason", "cleanup"); -client.deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567", metadata)); - -// You can also optionally specify a ClientCallContext with call-specific config to use -client.deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567", clientCallContext); -``` - -#### Subscribe to a task - -```java -// Subscribe to an ongoing task with id "task-1234" using configured consumers -TaskIdParams taskIdParams = new TaskIdParams("task-1234"); -client.subscribeToTask(taskIdParams); - -// Or subscribe with custom consumers and error handler -List> customConsumers = List.of( - (event, card) -> System.out.println("Subscribe event: " + event) -); -Consumer customErrorHandler = error -> - System.err.println("Subscribe error: " + error.getMessage()); - -client.subscribeToTask(taskIdParams, customConsumers, customErrorHandler); - -// You can also optionally specify a ClientCallContext with call-specific config to use -client.subscribeToTask(taskIdParams, clientCallContext); -``` - -#### Retrieve details about the server agent that this client agent is communicating with -```java -AgentCard serverAgentCard = client.getAgentCard(); -``` - -## Additional Examples - -### Hello World Client Example - -A complete example of a Java A2A client communicating with a Python A2A server is available in the [examples/helloworld/client](examples/helloworld/client/README.md) directory. This example demonstrates: - -- Setting up and using the A2A Java client -- Sending regular and streaming messages to a Python A2A server -- Receiving and processing responses from the Python A2A server - -The example includes detailed instructions on how to run the Python A2A server and how to run the Java A2A client using JBang. - -Check out the [example's README](examples/helloworld/client/README.md) for more information. - -### Hello World Server Example - -A complete example of a Python A2A client communicating with a Java A2A server is available in the [examples/helloworld/server](examples/helloworld/server/README.md) directory. This example demonstrates: - -- A sample `AgentCard` producer -- A sample `AgentExecutor` producer -- A Java A2A server receiving regular and streaming messages from a Python A2A client - -Check out the [example's README](examples/helloworld/server/README.md) for more information. - -## Community Articles - -See [COMMUNITY_ARTICLES.md](COMMUNITY_ARTICLES.md) for a list of community articles and videos. - -## License - -This project is licensed under the terms of the [Apache 2.0 License](LICENSE). - -## Contributing - -See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines. - -## Server Integrations -The following list contains community contributed integrations with various Java Runtimes. - -To contribute an integration, please see [CONTRIBUTING_INTEGRATIONS.md](CONTRIBUTING_INTEGRATIONS.md). - -* [reference/jsonrpc/README.md](reference/jsonrpc/README.md) - JSON-RPC 2.0 Reference implementation, based on Quarkus. -* [reference/grpc/README.md](reference/grpc/README.md) - gRPC Reference implementation, based on Quarkus. -* https://github.com/wildfly-extras/a2a-java-sdk-server-jakarta - This integration is based on Jakarta EE, and should work in all runtimes supporting the [Jakarta EE Web Profile](https://jakarta.ee/specifications/webprofile/). - -# Extras -See the [`extras`](./extras/README.md) folder for extra functionality not provided by the SDK itself! - diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 079a18e94..000000000 --- a/RELEASE.md +++ /dev/null @@ -1,274 +0,0 @@ -# Release Process - -This document describes the process for releasing a new version of the A2A Java SDK to Maven Central. - -## Overview - -The release process involves: -1. Updating version numbers across the project (automated) -2. Opening and merging a release PR -3. Tagging the release -4. Automatic deployment to Maven Central -5. Automatic GitHub release creation -6. Incrementing to next SNAPSHOT version - -## Prerequisites - -### Required Accounts & Access -- GitHub repository write access to `a2aproject/a2a-java` -- Maven Central account: namespace: `io.github.a2asdk` - -### Required Secrets (Repository Maintainers) -The following secrets must be configured in GitHub repository settings: -- `GPG_SIGNING_KEY`: Private GPG key for artifact signing -- `GPG_SIGNING_PASSPHRASE`: Passphrase for the GPG key -- `CENTRAL_TOKEN_USERNAME`: Maven Central username token -- `CENTRAL_TOKEN_PASSWORD`: Maven Central password token - -## Release Steps - -The examples below use versions like `0.4.0.Alpha1-SNAPSHOT` and `0.4.0.Alpha1` for demonstration. Be sure to substitute these with the actual versions for your release. - -### 1. Prepare Release Version - -Use the provided script to update all version numbers: - -```bash -# Preview changes (dry run) -./update-version.sh 0.4.0.Alpha1-SNAPSHOT 0.4.0.Alpha1 --dry-run - -# Apply version update -./update-version.sh 0.4.0.Alpha1-SNAPSHOT 0.4.0.Alpha1 -``` - -The script automatically updates: -- ✅ All `pom.xml` files -- ✅ All JBang script `//DEPS` declarations in `examples/` -- ✅ Validates the JBang update with built-in GMavenPlus validation - -**What gets updated**: -``` -pom.xml: 0.4.0.Alpha1-SNAPSHOT → 0.4.0.Alpha1 -//DEPS io.github...: 0.4.0.Alpha1-SNAPSHOT → 0.4.0.Alpha1 -``` - -### 2. Verify Changes - -Review the changes before committing: - -```bash -# Review all changes -git diff - -# Verify build works -mvn clean install -``` - -### 3. Create Release PR - -Create a pull request with the version update: - -```bash -git checkout -b release/0.4.0.Alpha1 -git add -A -git commit -m "chore: release 0.4.0.Alpha1" -git push origin release/0.4.0.Alpha1 -``` - -Open PR on GitHub with title: `chore: release 0.4.0.Alpha1` - -### 4. CI Verification - -The `build-with-release-profile.yml` workflow automatically verifies: -- ✅ Build succeeds with `-Prelease` profile -- ✅ All JavaDoc generation succeeds -- ✅ GPG signing works correctly -- ✅ JBang version validation passes -- ✅ No compilation or test failures - -**Important**: This workflow tests the actual PR branch (not main) to catch issues before merge. - -Wait for all CI checks to pass before proceeding. - -### 5. Merge Release PR - -Once all checks pass and the PR is approved: -- Merge the PR to `main` branch -- **Do NOT squash** - keep the release commit message intact for changelog - -### 6. Tag and Push - -After the PR is merged to main: - -```bash -# Switch to main and pull the merged changes -git checkout main -git pull origin main - -# Create annotated tag -git tag -a v0.4.0.Alpha1 -m "Release 0.4.0.Alpha1" - -# Push the tag (triggers deployment + GitHub release) -git push origin v0.4.0.Alpha1 -``` - -### 7. Automated Workflows Triggered - -Pushing the tag triggers **two workflows**: - -#### A. Maven Central Deployment (`release-to-maven-central.yml`) -1. Detects tag (pattern: `v?[0-9]+.[0-9]+.[0-9]+*`) -2. Checks out the tagged commit -3. Builds with `-Prelease -DskipTests` -4. Signs all artifacts with GPG -5. Deploys to Maven Central with auto-publish - -**⏱️ Deployment typically takes 30 minutes**, but can vary. - -#### B. GitHub Release Creation (`create-github-release.yml`) -1. Detects the same tag -2. Extracts version from tag name -3. Generates release notes from commits since last release -4. Creates GitHub release with: - - Auto-generated changelog - - Link to Maven Central artifacts - - Installation instructions - -### 8. Verify Deployment - -Check that artifacts are available: - -**Maven Central**: -``` -https://central.sonatype.com/artifact/io.github.a2asdk/a2a-java-sdk-parent/0.4.0.Alpha1 -``` - -**GitHub Release**: -``` -https://github.com/a2aproject/a2a-java/releases/tag/v0.4.0.Alpha1 -``` - -Artifacts should include: -- `.jar` files (main artifacts) -- `-sources.jar` (source code) -- `-javadoc.jar` (JavaDoc) -- `.pom` files -- `.asc` GPG signatures for all artifacts - -### 9. Increment to Next SNAPSHOT - -Prepare repository for next development cycle: - -```bash -# Update to next SNAPSHOT version -./update-version.sh 0.4.0.Alpha1 0.4.0.Alpha2-SNAPSHOT - -# Create and push PR -git checkout -b chore/bump-to-0.4.0.Alpha2-SNAPSHOT -git add -A -git commit -m "chore: bump version to 0.4.0.Alpha2-SNAPSHOT" -git push origin chore/bump-to-0.4.0.Alpha2-SNAPSHOT -``` - -Open PR, wait for CI, and merge. - -## Troubleshooting - -### Build fails with "JBang version mismatch" - -**Cause**: JBang script dependencies don't match POM version - -**Fix**: -```bash -# Re-run the update script to fix mismatches -./update-version.sh OLD_VERSION NEW_VERSION - -# Or manually check: -grep -r "//DEPS io.github.a2asdk:" examples/ -``` - -### GPG signing fails in workflow - -**Cause**: GPG secrets are missing or incorrect - -**Fix**: Repository maintainers - verify secrets in: -``` -Settings → Secrets and variables → Actions -``` -Check: `GPG_SIGNING_KEY`, `GPG_SIGNING_PASSPHRASE` - -### Maven Central deployment times out - -**Cause**: Normal Maven Central processing delays - -**Fix**: Wait (up to 2 hours). Check status: -``` -https://central.sonatype.com/publishing -``` - -### Deployment fails with authentication error - -**Cause**: Maven Central tokens expired or incorrect - -**Fix**: Repository maintainers: -1. Log in to Maven Central with the GitHub account for the a2asdk user. -2. Generate new tokens: `User → Generate User Token` -3. Update secrets: `CENTRAL_TOKEN_USERNAME` and `CENTRAL_TOKEN_PASSWORD` - -### GitHub release not created - -**Cause**: Workflow failed or tag pattern didn't match - -**Fix**: -```bash -# Check workflow runs -https://github.com/a2aproject/a2a-java/actions - -# Manually create release if needed -https://github.com/a2aproject/a2a-java/releases/new -``` - -### Need to rollback a release - -**Not possible** - Maven Central does not allow artifact deletion. - -**Mitigation**: -1. Release a patch version with fixes (e.g., `0.4.0.Alpha1` → `0.4.0.Alpha2`) -2. Document issues in GitHub release notes -3. Update documentation to recommend correct version - -## Version Numbering - -Follow semantic versioning with qualifiers: - -- **Major.Minor.Patch** - Standard releases (e.g., `1.0.0`) -- **Major.Minor.Patch.AlphaN** - Alpha releases (e.g., `0.4.0.Alpha1`) -- **Major.Minor.Patch.BetaN** - Beta releases (e.g., `0.3.0.Beta1`) -- **Major.Minor.Patch.RCN** - Release candidates (e.g., `1.0.0.RC1`) -- **-SNAPSHOT** - Development versions (e.g., `0.4.0.Alpha2-SNAPSHOT`) - -## Workflows Reference - -### build-with-release-profile.yml -- **Triggers**: All PRs, all pushes -- **Purpose**: Verify builds with `-Prelease` profile -- **Special**: Tests actual PR branch (not main) using `pull_request_target` with explicit checkout -- **Requires**: GPG and Maven Central secrets - -### release-to-maven-central.yml -- **Triggers**: Tags matching `v?[0-9]+.[0-9]+.[0-9]+*` -- **Purpose**: Deploy to Maven Central -- **Duration**: ~30 minutes -- **Requires**: GPG and Maven Central secrets - -### create-github-release.yml -- **Triggers**: Tags matching `v?[0-9]+.[0-9]+.[0-9]+*` -- **Purpose**: Create GitHub release with changelog -- **Features**: Auto-generated release notes, Maven Central links -- **Requires**: Default `GITHUB_TOKEN` (automatic) - -## Support - -For questions or issues with the release process: -- Open an issue: https://github.com/a2aproject/a2a-java/issues -- Reference: [Issue #532](https://github.com/a2aproject/a2a-java/issues/532) - Release process improvements diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 36c3d8d4b..000000000 --- a/SECURITY.md +++ /dev/null @@ -1,31 +0,0 @@ -# Reporting of CVEs and Security Issues - -## The A2A Java SDK community takes security bugs very seriously - -We aim to take immediate action to address serious security-related problems that involve our project. - -Note that we will only fix such issues in the most recent minor release of the A2A Java SDK. - -## Reporting of Security Issues - -When reporting a security vulnerability it is important to not accidentally broadcast to the world that -the issue exists, as this makes it easier for people to exploit it. The software industry uses the term -embargo to describe the time a -security issue is known internally until it is public knowledge. - -Our preferred way of reporting security issues is listed below. - -### Email the A2A Java SDK team - -To report a security issue, please email fjuma@redhat.com, -kkhan@redhat.com, and/or smaestri@redhat.com. A member of the team will open the required issues. - -### Other considerations - -If you would like to work with us on a fix for the security vulnerability, please include your GitHub username -in the above email, and we will provide you access to a temporary private fork where we can collaborate on a -fix without it being disclosed publicly, **including in your own publicly visible git repository**. - -Do not open a public issue, send a pull request, or disclose any information about the suspected vulnerability -publicly, **including in your own publicly visible git repository**. If you discover any publicly disclosed -security vulnerabilities, please notify us immediately through the emails listed in the section above. \ No newline at end of file diff --git a/boms/README.md b/boms/README.md deleted file mode 100644 index 79b2639c9..000000000 --- a/boms/README.md +++ /dev/null @@ -1,230 +0,0 @@ -# A2A Java SDK - Bill of Materials (BOM) - -This directory contains Bill of Materials (BOM) modules for the A2A Java SDK project, providing dependency management for external users. - -## Overview - -The A2A Java SDK provides three BOMs for different use cases: - -1. **`a2a-java-sdk-bom`** - Core SDK BOM for general A2A agent development -2. **`a2a-java-sdk-extras-bom`** - Extras BOM with server-side enhancements (task stores, queue managers) -3. **`a2a-java-sdk-reference-bom`** - Reference implementations BOM with Quarkus dependencies - -## BOM Modules - -### SDK BOM (`boms/sdk`) - -**Artifact:** `io.github.a2asdk:a2a-java-sdk-bom` - -The SDK BOM includes: -- All A2A SDK core modules (spec, server, client, transport) -- Core third-party dependencies (Jackson, gRPC, SLF4J) -- Jakarta APIs (CDI, Inject, JSON, JAX-RS) -- Test utilities - -**Use this BOM when:** Building A2A agents with any framework (Quarkus, Spring Boot, vanilla Java, etc.) - -### Extras BOM (`boms/extras`) - -**Artifact:** `io.github.a2asdk:a2a-java-sdk-extras-bom` - -The Extras BOM includes: -- Everything from `a2a-java-sdk-bom` (via import) -- Server-side enhancement modules (database persistence, distributed queue management, etc.) - -**Use this BOM when:** Building production A2A servers needing advanced server-side features beyond the core SDK - -### Reference BOM (`boms/reference`) - -**Artifact:** `io.github.a2asdk:a2a-java-sdk-reference-bom` - -The Reference BOM includes: -- Everything from `a2a-java-sdk-bom` (via import) -- Quarkus BOM (complete Quarkus platform) -- A2A reference implementation modules (JSON-RPC, gRPC, REST) -- TCK module for testing - -**Use this BOM when:** Building Quarkus-based A2A agents or reference implementations - -## Usage - -### For SDK Users (Any Framework) - -Add to your project's `pom.xml`: - -```xml - - - - io.github.a2asdk - a2a-java-sdk-bom - ${io.a2a.sdk.version} - pom - import - - - - - - - - io.github.a2asdk - a2a-java-sdk-server-common - - - io.github.a2asdk - a2a-java-sdk-transport-jsonrpc - - -``` - -### For Extras Users (Database Persistence, Distributed Deployments) - -Add to your project's `pom.xml`: - -```xml - - - - io.github.a2asdk - a2a-java-sdk-extras-bom - ${io.a2a.sdk.version} - pom - import - - - - - - - - io.github.a2asdk - a2a-java-sdk-server-common - - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - - -``` - -### For Quarkus Reference Implementation Users - -Add to your project's `pom.xml`: - -```xml - - - - io.github.a2asdk - a2a-java-sdk-reference-bom - ${io.a2a.sdk.version} - pom - import - - - - - - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - - io.quarkus - quarkus-arc - - -``` - -## Internal Project Usage - -**Important:** The A2A Java SDK project itself does **NOT** import these BOMs in the parent `pom.xml`. The BOMs are -for the convenience of external users. - -### Maintenance Strategy - -- Parent `pom.xml` `` is the **single source of truth** for versions -- BOMs are **maintained to match** parent pom versions -- When updating dependencies, update **both** parent pom and relevant BOMs -- BOMs are separate artifacts for **external consumption only** - -## Automated Testing - -All three BOMs include **maven-invoker-plugin** integration tests that automatically verify: -- ✅ BOM can be imported correctly -- ✅ All declared dependencies resolve -- ✅ No missing versions or conflicts -- ✅ Code using the BOM compiles successfully - -### Test Structure - -``` -boms/ -├── sdk/ -│ └── src/it/ -│ ├── settings.xml # Test repository config -│ └── sdk-usage-test/ # Integration test project -│ ├── pom.xml # Imports SDK BOM -│ └── src/main/java/ # Test code using SDK -├── extras/ -│ └── src/it/ -│ └── extras-usage-test/ # Integration test project -│ ├── pom.xml # Imports Extras BOM -│ └── src/main/java/ # Test code using SDK + Extras -└── reference/ - └── src/it/ - └── reference-usage-test/ # Integration test project - ├── pom.xml # Imports Reference BOM - └── src/main/java/ # Test code using Quarkus + SDK -``` - -### Running Tests - -Tests run automatically during `mvn install`: - -```bash -# Test all BOMs -mvn clean install -DskipTests -pl boms/sdk,boms/extras,boms/reference - -# Test individual BOM -mvn clean install -DskipTests -pl boms/sdk -``` - -**What happens:** -1. BOM is installed to `target/local-repo/` -2. Test project builds using the BOM -3. If compilation succeeds → BOM is valid ✅ -4. If dependencies missing → Build fails ❌ - -## Maintenance Guidelines - -When updating dependencies in the project: - -1. **Update parent `pom.xml`** - Change version properties and dependencyManagement -2. **Update SDK BOM** (`boms/sdk/pom.xml`) - Sync core dependency versions -3. **Update Extras BOM** (`boms/extras/pom.xml`) - Sync if extras modules changed -4. **Update Reference BOM** (`boms/reference/pom.xml`) - Sync if Quarkus or reference modules changed -5. **Run automated tests** - Integration tests will catch any missing dependencies: - ```bash - mvn clean install -DskipTests -pl boms/sdk,boms/extras,boms/reference - ``` - -### Adding New Dependencies to BOMs - -When adding new SDK modules or dependencies: - -1. Add to appropriate BOM's `` -2. Add usage example in `src/it/*/src/main/java/` test code -3. Run tests to verify compilation -4. Tests will fail if versions are missing or incorrect - -## Version Alignment - -The BOMs use `${project.version}` for all A2A SDK modules, ensuring: -- BOMs always reference the correct SDK version -- Version updates only need to change parent pom -- No version drift between BOMs and SDK modules - -Maven's reactor automatically orders them correctly based on their `` declarations, regardless of their position in the parent pom's `` section. \ No newline at end of file diff --git a/boms/extras/pom.xml b/boms/extras/pom.xml deleted file mode 100644 index 05549454a..000000000 --- a/boms/extras/pom.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-sdk-extras-bom - pom - - A2A Java SDK - Extras BOM - Bill of Materials for A2A SDK Extras modules (task stores, queue managers, etc.) - - - - - - ${project.groupId} - a2a-java-sdk-bom - ${project.version} - pom - import - - - - - ${project.groupId} - a2a-java-extras-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-http-client-vertx - ${project.version} - - - ${project.groupId} - a2a-java-sdk-opentelemetry-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-opentelemetry-client - ${project.version} - - - ${project.groupId} - a2a-java-sdk-opentelemetry-client-propagation - ${project.version} - - - ${project.groupId} - a2a-java-sdk-opentelemetry-server - ${project.version} - - - ${project.groupId} - a2a-java-extras-task-store-database-jpa - ${project.version} - - - ${project.groupId} - a2a-java-extras-push-notification-config-store-database-jpa - ${project.version} - - - ${project.groupId} - a2a-java-queue-manager-replicated-core - ${project.version} - - - ${project.groupId} - a2a-java-queue-manager-replication-mp-reactive - ${project.version} - - - - - - - - ${project.groupId} - a2a-java-sdk-bom - ${project.version} - pom - - - - - - - org.apache.maven.plugins - maven-invoker-plugin - 3.8.0 - - ${project.build.directory}/it - ${project.build.directory}/local-repo - src/it/settings.xml - - clean - verify - - false - true - invoker.properties - - - io.github.a2asdk:a2a-java-bom-test-utils:${project.version}:jar - - - - - integration-test - - install - run - - - - - - - - diff --git a/boms/extras/src/it/extras-usage-test/invoker.properties b/boms/extras/src/it/extras-usage-test/invoker.properties deleted file mode 100644 index ff2d26065..000000000 --- a/boms/extras/src/it/extras-usage-test/invoker.properties +++ /dev/null @@ -1,2 +0,0 @@ -invoker.goals=clean verify -invoker.buildResult=success diff --git a/boms/extras/src/it/extras-usage-test/pom.xml b/boms/extras/src/it/extras-usage-test/pom.xml deleted file mode 100644 index 5ec29b3a6..000000000 --- a/boms/extras/src/it/extras-usage-test/pom.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - 4.0.0 - - io.github.a2asdk.it - extras-bom-usage-test - 1.0-SNAPSHOT - jar - - Extras BOM Usage Test - Integration test to verify Extras BOM completeness - - - 17 - 17 - UTF-8 - - - - - - - io.github.a2asdk - a2a-java-sdk-extras-bom - @project.version@ - pom - import - - - - - - - - io.github.a2asdk - a2a-java-bom-test-utils - @project.version@ - - - - - io.github.a2asdk - a2a-java-extras-common - - - io.github.a2asdk - a2a-java-sdk-http-client-vertx - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-common - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-client - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-client-propagation - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-server - - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - - - io.github.a2asdk - a2a-java-extras-push-notification-config-store-database-jpa - - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - - - io.github.a2asdk - a2a-java-queue-manager-replication-mp-reactive - - - - - io.github.a2asdk - a2a-java-sdk-spec - - - io.github.a2asdk - a2a-java-sdk-spec-grpc - - - io.github.a2asdk - a2a-java-sdk-server-common - - - io.github.a2asdk - a2a-java-sdk-microprofile-config - - - io.github.a2asdk - a2a-java-sdk-client - - - io.github.a2asdk - a2a-java-sdk-client-transport-grpc - - - io.github.a2asdk - a2a-java-sdk-client-transport-jsonrpc - - - io.github.a2asdk - a2a-java-sdk-client-transport-rest - - - io.github.a2asdk - a2a-java-sdk-transport-jsonrpc - - - io.github.a2asdk - a2a-java-sdk-transport-grpc - - - io.github.a2asdk - a2a-java-sdk-transport-rest - - - - - org.eclipse.microprofile.config - microprofile-config-api - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - - - org.codehaus.mojo - exec-maven-plugin - 3.1.0 - - - verify-bom-completeness - verify - - java - - - io.a2a.test.ExtrasBomVerifier - - - - - - - diff --git a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java b/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java deleted file mode 100644 index 81cd0b855..000000000 --- a/boms/extras/src/it/extras-usage-test/src/main/java/io/a2a/test/ExtrasBomVerifier.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.a2a.test; - -import io.a2a.bom.test.DynamicBomVerifier; - -import java.util.Set; - -/** - * Verifies Extras BOM completeness by attempting to load all discovered classes. - * - Includes SDK modules + Extras modules (task stores, queue managers, etc.) - * - Forbids reference/ to prove BOM doesn't leak reference implementation dependencies - */ -public class ExtrasBomVerifier extends DynamicBomVerifier { - - private static final Set EXTRAS_EXCLUSIONS = Set.of( - "boms/", // BOM test modules themselves - "examples/", // Example applications - "tck/", // TCK test suite - "tests/", // Integration tests - "extras/queue-manager-replicated/tests-multi-instance/", // Test harness applications - "extras/queue-manager-replicated/tests-single-instance/", // Test harness applications - "extras/opentelemetry/integration-tests/" // Test harness applications - // Note: extras/ production modules are NOT in this list - we want to verify those classes load - ); - - private static final Set EXTRAS_FORBIDDEN = Set.of( - "reference/" // Reference implementations (separate BOM) - must NOT be loadable - ); - - public ExtrasBomVerifier() { - super(EXTRAS_EXCLUSIONS, EXTRAS_FORBIDDEN); - } - - public static void main(String[] args) throws Exception { - new ExtrasBomVerifier().verify(); - } -} diff --git a/boms/extras/src/it/settings.xml b/boms/extras/src/it/settings.xml deleted file mode 100644 index c06ed6333..000000000 --- a/boms/extras/src/it/settings.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - it-repo - - true - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - diff --git a/boms/reference/pom.xml b/boms/reference/pom.xml deleted file mode 100644 index 7a70b7f61..000000000 --- a/boms/reference/pom.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-sdk-reference-bom - pom - - A2A Java SDK - Reference Implementations BOM - Bill of Materials (BOM) for A2A Java SDK reference implementations with Quarkus dependencies - - - - - - ${project.groupId} - a2a-java-sdk-bom - ${project.version} - pom - import - - - - - io.quarkus - quarkus-bom - ${quarkus.platform.version} - pom - import - - - - - ${project.groupId} - a2a-java-sdk-reference-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-reference-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-reference-jsonrpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-reference-rest - ${project.version} - - - - - ${project.groupId} - a2a-java-sdk-tck - ${project.version} - - - - - - - - ${project.groupId} - a2a-java-sdk-bom - ${project.version} - pom - - - - - - - org.apache.maven.plugins - maven-invoker-plugin - 3.8.0 - - ${project.build.directory}/it - ${project.build.directory}/local-repo - src/it/settings.xml - - clean - verify - - false - true - invoker.properties - - - io.github.a2asdk:a2a-java-bom-test-utils:${project.version}:jar - - - - - integration-test - - install - run - - - - - - - - diff --git a/boms/reference/src/it/reference-usage-test/invoker.properties b/boms/reference/src/it/reference-usage-test/invoker.properties deleted file mode 100644 index ff2d26065..000000000 --- a/boms/reference/src/it/reference-usage-test/invoker.properties +++ /dev/null @@ -1,2 +0,0 @@ -invoker.goals=clean verify -invoker.buildResult=success diff --git a/boms/reference/src/it/reference-usage-test/pom.xml b/boms/reference/src/it/reference-usage-test/pom.xml deleted file mode 100644 index 5e7a500f3..000000000 --- a/boms/reference/src/it/reference-usage-test/pom.xml +++ /dev/null @@ -1,141 +0,0 @@ - - - 4.0.0 - - io.github.a2asdk.it - reference-bom-usage-test - 1.0-SNAPSHOT - jar - - Reference BOM Usage Test - Integration test to verify Reference BOM completeness including Quarkus - - - 17 - 17 - UTF-8 - - - - - - io.github.a2asdk - a2a-java-sdk-reference-bom - @project.version@ - pom - import - - - - - - - - io.github.a2asdk - a2a-java-bom-test-utils - @project.version@ - - - - - io.github.a2asdk - a2a-java-sdk-reference-common - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - - io.github.a2asdk - a2a-java-sdk-reference-grpc - - - io.github.a2asdk - a2a-java-sdk-reference-rest - - - - - io.github.a2asdk - a2a-java-sdk-spec - - - io.github.a2asdk - a2a-java-sdk-spec-grpc - - - io.github.a2asdk - a2a-java-sdk-server-common - - - io.github.a2asdk - a2a-java-sdk-microprofile-config - - - io.github.a2asdk - a2a-java-sdk-client - - - io.github.a2asdk - a2a-java-sdk-client-transport-grpc - - - io.github.a2asdk - a2a-java-sdk-client-transport-rest - - - io.github.a2asdk - a2a-java-sdk-transport-jsonrpc - - - - - org.eclipse.microprofile.config - microprofile-config-api - - - - - io.quarkus - quarkus-arc - - - io.quarkus - quarkus-grpc - - - io.quarkus - quarkus-rest - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - - - org.codehaus.mojo - exec-maven-plugin - 3.1.0 - - - verify-bom-completeness - verify - - java - - - io.a2a.test.ReferenceBomVerifier - - - - - - - diff --git a/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java b/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java deleted file mode 100644 index af73ded93..000000000 --- a/boms/reference/src/it/reference-usage-test/src/main/java/io/a2a/test/ReferenceBomVerifier.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.a2a.test; - -import io.a2a.bom.test.DynamicBomVerifier; - -import java.util.Set; - -/** - * Verifies Reference BOM completeness by attempting to load all discovered classes. - * - Includes SDK modules + Reference implementation modules - * - Forbids extras/ to prove BOM doesn't leak extras dependencies - */ -public class ReferenceBomVerifier extends DynamicBomVerifier { - - private static final Set REFERENCE_EXCLUSIONS = Set.of( - "boms/", // BOM test modules themselves - "examples/", // Example applications - "tck/", // TCK test suite - "tests/" // Integration tests - // Note: reference/ is NOT in this list - we want to verify those classes load - ); - - private static final Set REFERENCE_FORBIDDEN = Set.of( - "extras/" // Extras modules (separate BOM) - must NOT be loadable - ); - - public ReferenceBomVerifier() { - super(REFERENCE_EXCLUSIONS, REFERENCE_FORBIDDEN); - } - - public static void main(String[] args) throws Exception { - new ReferenceBomVerifier().verify(); - } -} diff --git a/boms/reference/src/it/settings.xml b/boms/reference/src/it/settings.xml deleted file mode 100644 index c06ed6333..000000000 --- a/boms/reference/src/it/settings.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - it-repo - - true - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml deleted file mode 100644 index c89cdc836..000000000 --- a/boms/sdk/pom.xml +++ /dev/null @@ -1,262 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-sdk-bom - pom - - A2A Java SDK - BOM - Bill of Materials (BOM) for A2A Java SDK core modules and dependencies - - - - - - - - ${project.groupId} - a2a-java-sdk-spec - ${project.version} - - - ${project.groupId} - a2a-java-sdk-spec-grpc - ${project.version} - - - - - ${project.groupId} - a2a-java-sdk-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-http-client - ${project.version} - - - - - ${project.groupId} - a2a-java-sdk-server-common - ${project.version} - - - - - ${project.groupId} - a2a-java-sdk-microprofile-config - ${project.version} - - - - - ${project.groupId} - a2a-java-sdk-client - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-jsonrpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-rest - ${project.version} - - - - - ${project.groupId} - a2a-java-sdk-transport-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-transport-jsonrpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-transport-rest - ${project.version} - - - - - ${project.groupId} - a2a-java-sdk-tests-server-common - ${project.version} - test - - - ${project.groupId} - a2a-java-sdk-tests-server-common - test-jar - test - ${project.version} - - - ${project.groupId} - a2a-java-sdk-server-common - test-jar - test - ${project.version} - - - - - io.grpc - grpc-bom - ${grpc.version} - pom - import - - - org.slf4j - slf4j-bom - ${slf4j.version} - pom - import - - - - - com.google.protobuf - protobuf-java - ${protobuf-java.version} - - - io.smallrye.reactive - mutiny-zero - ${mutiny-zero.version} - - - - - jakarta.enterprise - jakarta.enterprise.cdi-api - ${jakarta.enterprise.cdi-api.version} - - - jakarta.inject - jakarta.inject-api - ${jakarta.inject.jakarta.inject-api.version} - - - jakarta.json - jakarta.json-api - ${jakarta.json-api.version} - provided - - - jakarta.ws.rs - jakarta.ws.rs-api - ${jakarta.ws.rs-api.version} - provided - - - - - org.jspecify - jspecify - 1.0.0 - provided - - - - - org.junit.jupiter - junit-jupiter-api - ${junit.version} - test - - - io.rest-assured - rest-assured - ${rest-assured.version} - test - - - org.mockito - mockito-core - ${mockito-core.version} - test - - - org.mock-server - mockserver-netty - ${mockserver.version} - test - - - ch.qos.logback - logback-classic - ${logback.version} - test - - - - - - - - org.apache.maven.plugins - maven-invoker-plugin - 3.8.0 - - ${project.build.directory}/it - ${project.build.directory}/local-repo - src/it/settings.xml - - clean - verify - - false - true - invoker.properties - - - io.github.a2asdk:a2a-java-bom-test-utils:${project.version}:jar - - - - - integration-test - - install - run - - - - - - - - diff --git a/boms/sdk/src/it/sdk-usage-test/invoker.properties b/boms/sdk/src/it/sdk-usage-test/invoker.properties deleted file mode 100644 index dfd24e59e..000000000 --- a/boms/sdk/src/it/sdk-usage-test/invoker.properties +++ /dev/null @@ -1,8 +0,0 @@ -# Integration test configuration for maven-invoker-plugin -# This test verifies that the SDK BOM can be imported and used successfully - -# Expected goals to succeed -invoker.goals=clean verify - -# This test should pass -invoker.buildResult=success diff --git a/boms/sdk/src/it/sdk-usage-test/pom.xml b/boms/sdk/src/it/sdk-usage-test/pom.xml deleted file mode 100644 index d1e2388e4..000000000 --- a/boms/sdk/src/it/sdk-usage-test/pom.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - 4.0.0 - - io.github.a2asdk.it - sdk-bom-usage-test - 1.0-SNAPSHOT - jar - - SDK BOM Usage Test - Integration test to verify SDK BOM completeness - - - 17 - 17 - UTF-8 - - - - - - - io.github.a2asdk - a2a-java-sdk-bom - @project.version@ - pom - import - - - - - - - - io.github.a2asdk - a2a-java-bom-test-utils - @project.version@ - - - - - io.github.a2asdk - a2a-java-sdk-spec - - - io.github.a2asdk - a2a-java-sdk-spec-grpc - - - - - io.github.a2asdk - a2a-java-sdk-common - - - - - io.github.a2asdk - a2a-java-sdk-server-common - - - - - io.github.a2asdk - a2a-java-sdk-microprofile-config - - - - - io.github.a2asdk - a2a-java-sdk-client - - - io.github.a2asdk - a2a-java-sdk-client-transport-spi - - - io.github.a2asdk - a2a-java-sdk-client-transport-jsonrpc - - - io.github.a2asdk - a2a-java-sdk-client-transport-grpc - - - io.github.a2asdk - a2a-java-sdk-client-transport-rest - - - - - io.github.a2asdk - a2a-java-sdk-transport-jsonrpc - - - io.github.a2asdk - a2a-java-sdk-transport-grpc - - - io.github.a2asdk - a2a-java-sdk-transport-rest - - - - - org.slf4j - slf4j-api - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - io.smallrye.reactive - mutiny-zero - - - com.google.protobuf - protobuf-java - - - io.grpc - grpc-stub - - - org.eclipse.microprofile.config - microprofile-config-api - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - - - org.codehaus.mojo - exec-maven-plugin - 3.1.0 - - - verify-bom-completeness - verify - - java - - - io.a2a.test.SdkBomVerifier - - - - - - - diff --git a/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java b/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java deleted file mode 100644 index 036626c3f..000000000 --- a/boms/sdk/src/it/sdk-usage-test/src/main/java/io/a2a/test/SdkBomVerifier.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.a2a.test; - -import io.a2a.bom.test.DynamicBomVerifier; - -import java.util.Set; - -/** - * Verifies SDK BOM completeness by attempting to load all discovered classes. - * - Excludes paths not tested at all (boms/, examples/, tck/, tests/) - * - Forbids paths that must NOT be loadable (extras/, reference/) to prove BOM doesn't leak dependencies - */ -public class SdkBomVerifier extends DynamicBomVerifier { - - private static final Set SDK_EXCLUSIONS = Set.of( - "boms/", // BOM test modules themselves - "examples/", // Example applications - "tck/", // TCK test suite - "tests/" // Integration tests - ); - - private static final Set SDK_FORBIDDEN = Set.of( - "extras/", // Extras modules (separate BOM) - must NOT be loadable - "reference/" // Reference implementations (separate BOM) - must NOT be loadable - ); - - public SdkBomVerifier() { - super(SDK_EXCLUSIONS, SDK_FORBIDDEN); - } - - public static void main(String[] args) throws Exception { - new SdkBomVerifier().verify(); - } -} diff --git a/boms/sdk/src/it/settings.xml b/boms/sdk/src/it/settings.xml deleted file mode 100644 index c06ed6333..000000000 --- a/boms/sdk/src/it/settings.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - it-repo - - true - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - local.central - @localRepositoryUrl@ - - true - - - true - - - - - - diff --git a/boms/test-utils/pom.xml b/boms/test-utils/pom.xml deleted file mode 100644 index 4e67b3374..000000000 --- a/boms/test-utils/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-bom-test-utils - jar - - A2A Java SDK - BOM Test Utilities - Shared utilities for BOM integration tests - - - 17 - 17 - UTF-8 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.14.1 - - - - diff --git a/boms/test-utils/src/main/java/io/a2a/bom/test/DynamicBomVerifier.java b/boms/test-utils/src/main/java/io/a2a/bom/test/DynamicBomVerifier.java deleted file mode 100644 index 71b00e28a..000000000 --- a/boms/test-utils/src/main/java/io/a2a/bom/test/DynamicBomVerifier.java +++ /dev/null @@ -1,207 +0,0 @@ -package io.a2a.bom.test; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; -import org.jspecify.annotations.Nullable; - -/** - * Base class for dynamically discovering and verifying all classes in a BOM can be loaded. - * Subclass this and pass BOM-specific exclusions and forbidden paths to the constructor. - * - * - Excluded paths: Not tested at all (e.g., boms/, examples/, tck/, tests/) - * - Forbidden paths: Must NOT be loadable (proves BOM doesn't include wrong dependencies) - * - Required paths: Must be loadable (everything else) - */ -public abstract class DynamicBomVerifier { - - private final Set excludedPaths; - private final Set forbiddenPaths; - private static final Pattern PACKAGE_PATTERN = Pattern.compile("^package\\s+([a-zA-Z0-9_.]+);"); - - protected DynamicBomVerifier(Set excludedPaths, Set forbiddenPaths) { - this.excludedPaths = excludedPaths; - this.forbiddenPaths = forbiddenPaths; - } - - // Backwards compatibility constructor for verifiers without forbidden paths - protected DynamicBomVerifier(Set excludedPaths) { - this(excludedPaths, Set.of()); - } - - public void verify() throws Exception { - Path projectRoot = null; - Path current = Paths.get("").toAbsolutePath(); - while (current != null) { - if (Files.isDirectory(current)) { - if (Files.exists(current.resolve("pom.xml")) && Files.exists(current.resolve("boms"))) { - projectRoot = current; - break; - } - } - current = current.getParent(); - } - if (projectRoot == null) { - throw new IllegalStateException("Could not find project root directory."); - } - //Path projectRoot = Paths.get("").toAbsolutePath().getParent().getParent().getParent().getParent().getParent(); - System.out.println("Scanning project root: " + projectRoot); - - Set requiredClasses = discoverRequiredClasses(projectRoot); - Set forbiddenClasses = discoverForbiddenClasses(projectRoot); - - System.out.println("Discovered " + requiredClasses.size() + " required classes to verify"); - System.out.println("Discovered " + forbiddenClasses.size() + " forbidden classes to verify"); - - sanityCheckDiscovery(requiredClasses, forbiddenClasses); - - List failures = new ArrayList<>(); - int successful = 0; - - // Test required classes - must be loadable - for (String className : requiredClasses) { - try { - Class.forName(className); - successful++; - } catch (ClassNotFoundException e) { - failures.add("[REQUIRED] " + className + " - NOT FOUND"); - } catch (NoClassDefFoundError e) { - failures.add("[REQUIRED] " + className + " - MISSING DEPENDENCY: " + e.getMessage()); - } catch (Exception e) { - failures.add("[REQUIRED] " + className + " - ERROR: " + e.getMessage()); - } - } - - // Test forbidden classes - must NOT be loadable - int correctlyForbidden = 0; - for (String className : forbiddenClasses) { - try { - Class.forName(className); - failures.add("[FORBIDDEN] " + className + " - INCORRECTLY LOADABLE (BOM includes dependency it shouldn't!)"); - } catch (ClassNotFoundException | NoClassDefFoundError e) { - // Expected - class should not be loadable - correctlyForbidden++; - } catch (Exception e) { - failures.add("[FORBIDDEN] " + className + " - UNEXPECTED ERROR: " + e.getMessage()); - } - } - - System.out.println("\n=== BOM Verification Results ==="); - System.out.println("Required classes successfully loaded: " + successful + "/" + requiredClasses.size()); - System.out.println("Forbidden classes correctly not loadable: " + correctlyForbidden + "/" + forbiddenClasses.size()); - System.out.println("Total failures: " + failures.size()); - - if (!failures.isEmpty()) { - System.err.println("\n=== FAILURES ==="); - failures.forEach(System.err::println); - System.err.println("\nBOM verification FAILED!"); - System.exit(1); - } - - System.out.println("\n✅ BOM is COMPLETE - all required classes loaded, all forbidden classes not loadable!"); - } - - private void sanityCheckDiscovery(Set requiredClasses, Set forbiddenClasses) { - // Do some sanity checks for some classes from both top-level and nested modules to make sure the - // discovery mechanism worked properly - sanityCheckDiscovery("io.a2a.spec.AgentCard", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.server.events.EventConsumer", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.client.transport.spi.ClientTransport", requiredClasses, forbiddenClasses); - - sanityCheckDiscovery("io.a2a.server.common.quarkus.DefaultProducers", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.extras.common.events.TaskFinalizedEvent", requiredClasses, forbiddenClasses); - sanityCheckDiscovery("io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem", requiredClasses, forbiddenClasses); - - // Make sure that the required and forbidden sets don't contain the same classes - Set intersection = new HashSet<>(requiredClasses); - intersection.retainAll(forbiddenClasses); - if (!intersection.isEmpty()) { - System.err.println("The following classes appear in both the required and forbidden sets: " + intersection); - System.exit(1); - } - } - - private void sanityCheckDiscovery(String className, Set requiredClasses, Set forbiddenClasses) { - if (!requiredClasses.contains(className) && !forbiddenClasses.contains(className)) { - System.err.println("Class expected to be on the classpath was not discovered: " + className); - System.exit(1); - } - } - - /** - * Discover classes that MUST be loadable (not excluded, not forbidden) - */ - private Set discoverRequiredClasses(Path projectRoot) throws IOException { - return discoverClasses(projectRoot, relativePath -> !isExcluded(relativePath) && !isForbidden(relativePath)); - } - - /** - * Discover classes that must NOT be loadable (forbidden but not excluded) - */ - private Set discoverForbiddenClasses(Path projectRoot) throws IOException { - return discoverClasses(projectRoot, relativePath -> !isExcluded(relativePath) && isForbidden(relativePath)); - } - - /** - * Common discovery logic with custom filter - */ - private Set discoverClasses(Path projectRoot, java.util.function.Predicate pathFilter) throws IOException { - Set classes = new TreeSet<>(); - - try (Stream paths = Files.walk(projectRoot)) { - paths.filter(Files::isRegularFile) - .filter(p -> p.toString().endsWith(".java")) - .filter(p -> p.toString().contains("/src/main/java/")) - .filter(p -> pathFilter.test(projectRoot.relativize(p).toString())) - .forEach(javaFile -> { - try { - String className = extractClassName(javaFile); - if (className != null) { - classes.add(className); - } - } catch (IOException e) { - System.err.println("Failed to parse: " + javaFile + " - " + e.getMessage()); - } - }); - } - - return classes; - } - - private boolean isExcluded(String relativePath) { - return excludedPaths.stream().anyMatch(relativePath::startsWith); - } - - private boolean isForbidden(String relativePath) { - return forbiddenPaths.stream().anyMatch(relativePath::startsWith); - } - - private static @Nullable String extractClassName(Path javaFile) throws IOException { - // Extract simple class name from filename - String fileName = javaFile.getFileName().toString(); - if (!fileName.endsWith(".java")) { - return null; - } - String simpleClassName = fileName.substring(0, fileName.length() - 5); // Remove ".java" - - // Extract package name from file content - String packageName = null; - try (Stream lines = Files.lines(javaFile)) { - packageName = lines.map(String::trim) - .map(PACKAGE_PATTERN::matcher) - .filter(Matcher::matches) - .map(m -> m.group(1)) - .findFirst() - .orElse(null); - } - if (packageName != null) { - return packageName + "." + simpleClassName; - } - return null; - } -} diff --git a/boms/test-utils/src/main/java/io/a2a/bom/test/package-info.java b/boms/test-utils/src/main/java/io/a2a/bom/test/package-info.java deleted file mode 100644 index 98946de54..000000000 --- a/boms/test-utils/src/main/java/io/a2a/bom/test/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.bom.test; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/base/pom.xml b/client/base/pom.xml deleted file mode 100644 index 6de5dc8b9..000000000 --- a/client/base/pom.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-client - - jar - - Java SDK A2A Client - Java SDK for the Agent2Agent Protocol (A2A) - Client - - - - ${project.groupId} - a2a-java-sdk-http-client - - - ${project.groupId} - a2a-java-sdk-http-client-vertx - provided - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - - - ${project.groupId} - a2a-java-sdk-client-transport-jsonrpc - - - ${project.groupId} - a2a-java-sdk-client-transport-grpc - test - - - ${project.groupId} - a2a-java-sdk-client-transport-rest - test - - - ${project.groupId} - a2a-java-sdk-common - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-spec-grpc - test - - - org.junit.jupiter - junit-jupiter-api - test - - - - org.mock-server - mockserver-netty - test - - - org.slf4j - slf4j-jdk14 - test - - - io.grpc - grpc-testing - test - - - io.grpc - grpc-inprocess - test - - - - \ No newline at end of file diff --git a/client/base/src/main/java/io/a2a/A2A.java b/client/base/src/main/java/io/a2a/A2A.java deleted file mode 100644 index 14101b678..000000000 --- a/client/base/src/main/java/io/a2a/A2A.java +++ /dev/null @@ -1,399 +0,0 @@ -package io.a2a; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import io.a2a.client.http.A2ACardResolver; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientJSONError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; - - -/** - * Utility class providing convenience methods for working with the A2A Protocol. - *

- * This class offers static helper methods for common A2A operations: - *

    - *
  • Message creation: Simplified construction of user and agent messages
  • - *
  • Agent card retrieval: Fetching agent metadata from URLs
  • - *
- *

- * These utilities simplify client code by providing concise alternatives to the builder - * APIs for routine operations. - *

- * Example usage: - *

{@code
- * // Get agent card
- * AgentCard card = A2A.getAgentCard("http://localhost:9999");
- *
- * // Create and send a user message
- * Message userMsg = A2A.toUserMessage("What's the weather today?");
- * client.sendMessage(userMsg);
- *
- * // Create a message with context and task IDs
- * Message contextMsg = A2A.createUserTextMessage(
- *     "Continue the conversation",
- *     "session-123",  // contextId
- *     "task-456"      // taskId
- * );
- * client.sendMessage(contextMsg);
- * }
- * - * @see Message - * @see AgentCard - * @see io.a2a.client.Client - */ -public class A2A { - - /** - * Create a simple user message from text. - *

- * This is the most common way to create messages when sending requests to agents. - * The message will have: - *

    - *
  • role: USER
  • - *
  • parts: Single {@link io.a2a.spec.TextPart} with the provided text
  • - *
  • Auto-generated message ID
  • - *
- *

- * Example: - *

{@code
-     * Message msg = A2A.toUserMessage("Tell me a joke");
-     * client.sendMessage(msg);
-     * }
- * - * @param text the message text (required) - * @return a user message with the specified text - * @see #toUserMessage(String, String) - * @see #createUserTextMessage(String, String, String) - */ - public static Message toUserMessage(String text) { - return toMessage(text, Message.Role.ROLE_USER, null); - } - - /** - * Create a user message from text with a specific message ID. - *

- * Use this when you need to control the message ID for tracking or correlation purposes. - *

- * Example: - *

{@code
-     * String messageId = UUID.randomUUID().toString();
-     * Message msg = A2A.toUserMessage("Process this request", messageId);
-     * // Store messageId for later correlation
-     * client.sendMessage(msg);
-     * }
- * - * @param text the message text (required) - * @param messageId the message ID to use - * @return a user message with the specified text and ID - * @see #toUserMessage(String) - */ - public static Message toUserMessage(String text, String messageId) { - return toMessage(text, Message.Role.ROLE_USER, messageId); - } - - /** - * Create a simple agent message from text. - *

- * This is typically used in testing or when constructing agent responses programmatically. - * Most client applications receive agent messages via {@link io.a2a.client.MessageEvent} - * rather than creating them manually. - *

- * Example: - *

{@code
-     * // Testing scenario
-     * Message agentResponse = A2A.toAgentMessage("Here's the answer: 42");
-     * }
- * - * @param text the message text (required) - * @return an agent message with the specified text - * @see #toAgentMessage(String, String) - */ - public static Message toAgentMessage(String text) { - return toMessage(text, Message.Role.ROLE_AGENT, null); - } - - /** - * Create an agent message from text with a specific message ID. - *

- * Example: - *

{@code
-     * Message agentResponse = A2A.toAgentMessage("Processing complete", "msg-789");
-     * }
- * - * @param text the message text (required) - * @param messageId the message ID to use - * @return an agent message with the specified text and ID - */ - public static Message toAgentMessage(String text, String messageId) { - return toMessage(text, Message.Role.ROLE_AGENT, messageId); - } - - /** - * Create a user message with text content and optional context and task IDs. - *

- * This method is useful when continuing a conversation or working with a specific task: - *

    - *
  • contextId: Links message to a conversation session
  • - *
  • taskId: Associates message with an existing task
  • - *
- *

- * Example - continuing a conversation: - *

{@code
-     * // First message creates context
-     * Message msg1 = A2A.toUserMessage("What's your name?");
-     * client.sendMessage(msg1);
-     * String contextId = ...; // Get from response
-     *
-     * // Follow-up message uses contextId
-     * Message msg2 = A2A.createUserTextMessage(
-     *     "What else can you do?",
-     *     contextId,
-     *     null  // no specific task
-     * );
-     * client.sendMessage(msg2);
-     * }
- *

- * Example - adding to an existing task: - *

{@code
-     * Message msg = A2A.createUserTextMessage(
-     *     "Add this information too",
-     *     "session-123",
-     *     "task-456"  // Continue working on this task
-     * );
-     * client.sendMessage(msg);
-     * }
- * - * @param text the message text (required) - * @param contextId the context ID to use (optional) - * @param taskId the task ID to use (optional) - * @return a user message with the specified text, context, and task IDs - * @see #createAgentTextMessage(String, String, String) - * @see Message#contextId() - * @see Message#taskId() - */ - public static Message createUserTextMessage(String text, String contextId, String taskId) { - return toMessage(text, Message.Role.ROLE_USER, null, contextId, taskId); - } - - /** - * Create an agent message with text content and optional context and task IDs. - *

- * This is typically used in testing or when constructing agent responses programmatically. - * - * @param text the message text (required) - * @param contextId the context ID to use (optional) - * @param taskId the task ID to use (optional) - * @return an agent message with the specified text, context, and task IDs - * @see #createUserTextMessage(String, String, String) - */ - public static Message createAgentTextMessage(String text, String contextId, String taskId) { - return toMessage(text, Message.Role.ROLE_AGENT, null, contextId, taskId); - } - - /** - * Create an agent message with custom parts and optional context and task IDs. - *

- * This method allows creating messages with multiple parts (text, images, files, etc.) - * instead of just simple text. Useful for complex agent responses or testing. - *

- * Example - message with text and image: - *

{@code
-     * List> parts = List.of(
-     *     new TextPart("Here's a chart of the data:"),
-     *     new ImagePart("https://example.com/chart.png", "Chart showing sales data")
-     * );
-     * Message msg = A2A.createAgentPartsMessage(parts, "session-123", "task-456");
-     * }
- * - * @param parts the message parts (required, must not be empty) - * @param contextId the context ID to use (optional) - * @param taskId the task ID to use (optional) - * @return an agent message with the specified parts, context, and task IDs - * @throws IllegalArgumentException if parts is null or empty - * @see io.a2a.spec.Part - * @see io.a2a.spec.TextPart - */ - public static Message createAgentPartsMessage(List> parts, String contextId, String taskId) { - if (parts == null || parts.isEmpty()) { - throw new IllegalArgumentException("Parts cannot be null or empty"); - } - return toMessage(parts, Message.Role.ROLE_AGENT, null, contextId, taskId); - } - - private static Message toMessage(String text, Message.Role role, String messageId) { - return toMessage(text, role, messageId, null, null); - } - - private static Message toMessage(String text, Message.Role role, String messageId, String contextId, String taskId) { - Message.Builder messageBuilder = Message.builder() - .role(role) - .parts(Collections.singletonList(new TextPart(text))) - .contextId(contextId) - .taskId(taskId); - if (messageId != null) { - messageBuilder.messageId(messageId); - } - return messageBuilder.build(); - } - - private static Message toMessage(List> parts, Message.Role role, String messageId, String contextId, String taskId) { - Message.Builder messageBuilder = Message.builder() - .role(role) - .parts(parts) - .contextId(contextId) - .taskId(taskId); - if (messageId != null) { - messageBuilder.messageId(messageId); - } - return messageBuilder.build(); - } - - /** - * Retrieve the agent card for an A2A agent. - *

- * This is the standard way to discover an agent's capabilities before creating a client. - * The agent card is fetched from the well-known endpoint: {@code /.well-known/agent-card.json} - *

- * Example: - *

{@code
-     * // Get agent card
-     * AgentCard card = A2A.getAgentCard("http://localhost:9999");
-     *
-     * // Check capabilities
-     * System.out.println("Agent: " + card.name());
-     * System.out.println("Supports streaming: " + card.capabilities().streaming());
-     *
-     * // Create client
-     * Client client = Client.builder(card)
-     *     .withTransport(...)
-     *     .build();
-     * }
- * - * @param agentUrl the base URL for the agent whose agent card we want to retrieve - * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema - * @see #getAgentCard(A2AHttpClient, String) - * @see #getAgentCard(String, String, java.util.Map) - * @see AgentCard - */ - public static AgentCard getAgentCard(String agentUrl) throws A2AClientError, A2AClientJSONError { - return getAgentCard(A2AHttpClientFactory.create(), agentUrl); - } - - /** - * Retrieve the agent card using a custom HTTP client. - *

- * Use this variant when you need to customize HTTP behavior (timeouts, SSL configuration, - * connection pooling, etc.). - *

- * Example: - *

{@code
-     * A2AHttpClient customClient = new CustomHttpClient()
-     *     .withTimeout(Duration.ofSeconds(10))
-     *     .withSSLContext(mySSLContext);
-     *
-     * AgentCard card = A2A.getAgentCard(customClient, "https://secure-agent.com");
-     * }
- * - * @param httpClient the http client to use - * @param agentUrl the base URL for the agent whose agent card we want to retrieve - * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema - * @see io.a2a.client.http.A2AHttpClient - */ - public static AgentCard getAgentCard(A2AHttpClient httpClient, String agentUrl) throws A2AClientError, A2AClientJSONError { - return getAgentCard(httpClient, agentUrl, null, null); - } - - /** - * Retrieve the agent card with custom path and authentication. - *

- * Use this variant when: - *

    - *
  • The agent card is at a non-standard location
  • - *
  • Authentication is required to access the agent card
  • - *
- *

- * Example with authentication: - *

{@code
-     * Map authHeaders = Map.of(
-     *     "Authorization", "Bearer my-api-token",
-     *     "X-API-Key", "my-api-key"
-     * );
-     *
-     * AgentCard card = A2A.getAgentCard(
-     *     "https://secure-agent.com",
-     *     null,  // Use default path
-     *     authHeaders
-     * );
-     * }
- *

- * Example with custom path: - *

{@code
-     * AgentCard card = A2A.getAgentCard(
-     *     "https://agent.com",
-     *     "api/v2/agent-info",  // Custom path
-     *     null  // No auth needed
-     * );
-     * // Fetches from: https://agent.com/api/v2/agent-info
-     * }
- * - * @param agentUrl the base URL for the agent whose agent card we want to retrieve - * @param relativeCardPath optional path to the agent card endpoint relative to the base - * agent URL, defaults to ".well-known/agent-card.json" - * @param authHeaders the HTTP authentication headers to use - * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema - */ - public static AgentCard getAgentCard(String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError, A2AClientJSONError { - return getAgentCard(A2AHttpClientFactory.create(), agentUrl, relativeCardPath, authHeaders); - } - - /** - * Retrieve the agent card with full customization options. - *

- * This is the most flexible variant, allowing customization of: - *

    - *
  • HTTP client implementation
  • - *
  • Agent card endpoint path
  • - *
  • Authentication headers
  • - *
- *

- * Example: - *

{@code
-     * A2AHttpClient customClient = new CustomHttpClient();
-     * Map authHeaders = Map.of("Authorization", "Bearer token");
-     *
-     * AgentCard card = A2A.getAgentCard(
-     *     customClient,
-     *     "https://agent.com",
-     *     "custom/agent-card",
-     *     authHeaders
-     * );
-     * }
- * - * @param httpClient the http client to use - * @param agentUrl the base URL for the agent whose agent card we want to retrieve - * @param relativeCardPath optional path to the agent card endpoint relative to the base - * agent URL, defaults to ".well-known/agent-card.json" - * @param authHeaders the HTTP authentication headers to use - * @return the agent card - * @throws io.a2a.spec.A2AClientError if an HTTP error occurs fetching the card - * @throws io.a2a.spec.A2AClientJSONError if the response body cannot be decoded as JSON or validated against the AgentCard schema - */ - public static AgentCard getAgentCard(A2AHttpClient httpClient, String agentUrl, String relativeCardPath, Map authHeaders) throws A2AClientError, A2AClientJSONError { - A2ACardResolver resolver = new A2ACardResolver(httpClient, agentUrl, "", relativeCardPath, authHeaders); - return resolver.getAgentCard(); - } -} diff --git a/client/base/src/main/java/io/a2a/client/AbstractClient.java b/client/base/src/main/java/io/a2a/client/AbstractClient.java deleted file mode 100644 index 27cbadc7d..000000000 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ /dev/null @@ -1,440 +0,0 @@ -package io.a2a.client; - -import static io.a2a.util.Assert.checkNotNullParam; - -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - -/** - * Abstract class representing an A2A client. Provides a standard set - * of methods for interacting with an A2A agent, regardless of the underlying - * transport protocol. It supports sending messages, managing tasks, and - * handling event streams. - */ -public abstract class AbstractClient implements AutoCloseable { - - protected final @NonNull List> consumers; - protected final @Nullable Consumer streamingErrorHandler; - - public AbstractClient(@NonNull List> consumers) { - this(consumers, null); - } - - public AbstractClient(@NonNull List> consumers, @Nullable Consumer streamingErrorHandler) { - checkNotNullParam("consumers", consumers); - this.consumers = consumers; - this.streamingErrorHandler = streamingErrorHandler; - } - - /** - * Send a message to the remote agent. This method will automatically use - * the streaming or non-streaming approach as determined by the server's - * agent card and the client configuration. The configured client consumers - * will be used to handle messages, tasks, and update events received - * from the remote agent. The configured streaming error handler will be used - * if an error occurs during streaming. The configured client push notification - * configuration will get used for streaming. - * - * @param request the message - * @throws A2AClientException if sending the message fails for any reason - */ - public void sendMessage(@NonNull Message request) throws A2AClientException { - sendMessage(request, null); - } - - /** - * Send a message to the remote agent. This method will automatically use - * the streaming or non-streaming approach as determined by the server's - * agent card and the client configuration. The configured client consumers - * will be used to handle messages, tasks, and update events received - * from the remote agent. The configured streaming error handler will be used - * if an error occurs during streaming. The configured client push notification - * configuration will get used for streaming. - * - * @param request the message - * @param context optional client call context for the request - * @throws A2AClientException if sending the message fails for any reason - */ - public void sendMessage(@NonNull Message request, - @Nullable ClientCallContext context) throws A2AClientException { - sendMessage(request, consumers, streamingErrorHandler, context); - } - - /** - * Send a message to the remote agent. This method will automatically use - * the streaming or non-streaming approach as determined by the server's - * agent card and the client configuration. The specified client consumers - * will be used to handle messages, tasks, and update events received - * from the remote agent. The specified streaming error handler will be used - * if an error occurs during streaming. The configured client push notification - * configuration will get used for streaming. - * - * @param request the message - * @param consumers a list of consumers to pass responses from the remote agent to - * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs - * @throws A2AClientException if sending the message fails for any reason - */ - public void sendMessage(@NonNull Message request, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler) throws A2AClientException { - sendMessage(request, consumers, streamingErrorHandler, null); - } - - /** - * Send a message to the remote agent. This method will automatically use - * the streaming or non-streaming approach as determined by the server's - * agent card and the client configuration. The specified client consumers - * will be used to handle messages, tasks, and update events received - * from the remote agent. The specified streaming error handler will be used - * if an error occurs during streaming. The configured client push notification - * configuration will get used for streaming. - * - * @param request the message - * @param consumers a list of consumers to pass responses from the remote agent to - * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs - * @param context optional client call context for the request - * @throws A2AClientException if sending the message fails for any reason - */ - public abstract void sendMessage(@NonNull Message request, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Send a message to the remote agent. This method will automatically use - * the streaming or non-streaming approach as determined by the server's - * agent card and the client configuration. The configured client consumers - * will be used to handle messages, tasks, and update events received from - * the remote agent. The configured streaming error handler will be used - * if an error occurs during streaming. - * - * @param request the message - * @param pushNotificationConfiguration the push notification configuration that should be - * used if the streaming approach is used - * @param metadata the optional metadata to include when sending the message - * @throws A2AClientException if sending the message fails for any reason - */ - public void sendMessage(@NonNull Message request, - @Nullable PushNotificationConfig pushNotificationConfiguration, - @Nullable Map metadata) throws A2AClientException { - sendMessage(request, pushNotificationConfiguration, metadata, null); - } - - /** - * Send a message to the remote agent. This method will automatically use - * the streaming or non-streaming approach as determined by the server's - * agent card and the client configuration. The configured client consumers - * will be used to handle messages, tasks, and update events received from - * the remote agent. The configured streaming error handler will be used - * if an error occurs during streaming. - * - * @param request the message - * @param pushNotificationConfiguration the push notification configuration that should be - * used if the streaming approach is used - * @param metadata the optional metadata to include when sending the message - * @param context optional client call context for the request - * @throws A2AClientException if sending the message fails for any reason - */ - public abstract void sendMessage(@NonNull Message request, - @Nullable PushNotificationConfig pushNotificationConfiguration, - @Nullable Map metadata, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Send a message to the remote agent. This method will automatically use - * the streaming or non-streaming approach as determined by the server's - * agent card and the client configuration. The specified client consumers - * will be used to handle messages, tasks, and update events received - * from the remote agent. The specified streaming error handler will be used - * if an error occurs during streaming. The configured client push notification - * configuration will get used for streaming. - * - * @param params the request parameters - * @param consumers a list of consumers to pass responses from the remote agent to - * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs - * @param context optional client call context for the request - * @throws A2AClientException if sending the message fails for any reason - */ - public abstract void sendMessage(@NonNull MessageSendParams params, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the current state and history of a specific task. - * - * @param request the task query parameters specifying which task to retrieve - * @return the task - * @throws A2AClientException if retrieving the task fails for any reason - */ - public Task getTask(TaskQueryParams request) throws A2AClientException { - return getTask(request, null); - } - - /** - * Retrieve the current state and history of a specific task. - * - * @param request the task query parameters specifying which task to retrieve - * @param context optional client call context for the request (may be {@code null}) - * @return the task - * @throws A2AClientException if retrieving the task fails for any reason - */ - public abstract Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * List tasks with optional filtering and pagination. - * - * @param request the list tasks parameters including filters and pagination - * @return the list tasks result containing tasks and pagination information - * @throws A2AClientException if listing tasks fails for any reason - */ - public ListTasksResult listTasks(ListTasksParams request) throws A2AClientException { - return listTasks(request, null); - } - - /** - * List tasks with optional filtering and pagination. - * - * @param request the list tasks parameters including filters and pagination - * @param context optional client call context for the request (may be {@code null}) - * @return the list tasks result containing tasks and pagination information - * @throws A2AClientException if listing tasks fails for any reason - */ - public abstract ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Request the agent to cancel a specific task. - * - * @param request the task ID parameters specifying which task to cancel - * @return the cancelled task - * @throws A2AClientException if cancelling the task fails for any reason - */ - public Task cancelTask(TaskIdParams request) throws A2AClientException { - return cancelTask(request, null); - } - - /** - * Request the agent to cancel a specific task. - * - * @param request the task ID parameters specifying which task to cancel - * @param context optional client call context for the request (may be {@code null}) - * @return the cancelled task - * @throws A2AClientException if cancelling the task fails for any reason - */ - public abstract Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Create or update the push notification configuration for a specific task. - * - * @param request the push notification configuration to set for the task - * @return the configured TaskPushNotificationConfig - * @throws A2AClientException if setting the task push notification configuration fails for any reason - */ - public TaskPushNotificationConfig createTaskPushNotificationConfiguration( - TaskPushNotificationConfig request) throws A2AClientException { - return createTaskPushNotificationConfiguration(request, null); - } - - /** - * Create or update the push notification configuration for a specific task. - * - * @param request the push notification configuration to set for the task - * @param context optional client call context for the request (may be {@code null}) - * @return the configured TaskPushNotificationConfig - * @throws A2AClientException if setting the task push notification configuration fails for any reason - */ - public abstract TaskPushNotificationConfig createTaskPushNotificationConfiguration( - TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the push notification configuration for a specific task. - * - * @param request the parameters specifying which task's notification config to retrieve - * @return the task push notification config - * @throws A2AClientException if getting the task push notification config fails for any reason - */ - public TaskPushNotificationConfig getTaskPushNotificationConfiguration( - GetTaskPushNotificationConfigParams request) throws A2AClientException { - return getTaskPushNotificationConfiguration(request, null); - } - - /** - * Retrieve the push notification configuration for a specific task. - * - * @param request the parameters specifying which task's notification config to retrieve - * @param context optional client call context for the request (may be {@code null}) - * @return the task push notification config - * @throws A2AClientException if getting the task push notification config fails for any reason - */ - public abstract TaskPushNotificationConfig getTaskPushNotificationConfiguration( - GetTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the list of push notification configurations for a specific task with pagination support. - * - * @param request the parameters specifying which task's notification configs to retrieve - * @return the result containing the list of task push notification configs and pagination information - * @throws A2AClientException if getting the task push notification configs fails for any reason - */ - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request) throws A2AClientException { - return listTaskPushNotificationConfigurations(request, null); - } - - /** - * Retrieve the list of push notification configurations for a specific task with pagination support. - * - * @param request the parameters specifying which task's notification configs to retrieve - * @param context optional client call context for the request (may be {@code null}) - * @return the result containing the list of task push notification configs and pagination information - * @throws A2AClientException if getting the task push notification configs fails for any reason - */ - public abstract ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Delete the list of push notification configurations for a specific task. - * - * @param request the parameters specifying which task's notification configs to delete - * @throws A2AClientException if deleting the task push notification configs fails for any reason - */ - public void deleteTaskPushNotificationConfigurations( - DeleteTaskPushNotificationConfigParams request) throws A2AClientException { - deleteTaskPushNotificationConfigurations(request, null); - } - - /** - * Delete the list of push notification configurations for a specific task. - * - * @param request the parameters specifying which task's notification configs to delete - * @param context optional client call context for the request (may be {@code null}) - * @throws A2AClientException if deleting the task push notification configs fails for any reason - */ - public abstract void deleteTaskPushNotificationConfigurations( - DeleteTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Subscribe to a task's event stream. - * This is only available if both the client and server support streaming. - * The configured client consumers will be used to handle messages, tasks, - * and update events received from the remote agent. The configured streaming - * error handler will be used if an error occurs during streaming. - * - * @param request the parameters specifying which task's notification configs to delete - * @throws A2AClientException if resubscribing fails for any reason - */ - public void subscribeToTask(@NonNull TaskIdParams request) throws A2AClientException { - subscribeToTask(request, consumers, streamingErrorHandler, null); - } - - /** - * Subscribe to a task's event stream. - * This is only available if both the client and server support streaming. - * The configured client consumers will be used to handle messages, tasks, - * and update events received from the remote agent. The configured streaming - * error handler will be used if an error occurs during streaming. - * - * @param request the parameters specifying which task's notification configs to delete - * @param context optional client call context for the request - * @throws A2AClientException if resubscribing fails for any reason - */ - public void subscribeToTask(@NonNull TaskIdParams request, - @Nullable ClientCallContext context) throws A2AClientException { - subscribeToTask(request, consumers, streamingErrorHandler, context); - } - - /** - * Subscribe to a task's event stream. - * This is only available if both the client and server support streaming. - * The specified client consumers will be used to handle messages, tasks, and - * update events received from the remote agent. The specified streaming error - * handler will be used if an error occurs during streaming. - * - * @param request the parameters specifying which task's notification configs to delete - * @param consumers a list of consumers to pass responses from the remote agent to - * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs - * @throws A2AClientException if resubscribing fails for any reason - */ - public void subscribeToTask(@NonNull TaskIdParams request, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler) throws A2AClientException { - subscribeToTask(request, consumers, streamingErrorHandler, null); - } - - /** - * Subscribe to a task's event stream. - * This is only available if both the client and server support streaming. - * The specified client consumers will be used to handle messages, tasks, and - * update events received from the remote agent. The specified streaming error - * handler will be used if an error occurs during streaming. - * - * @param request the parameters specifying which task's notification configs to delete - * @param consumers a list of consumers to pass responses from the remote agent to - * @param streamingErrorHandler an error handler that should be used for the streaming case if an error occurs - * @param context optional client call context for the request - * @throws A2AClientException if resubscribing fails for any reason - */ - public abstract void subscribeToTask(@NonNull TaskIdParams request, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the extended AgentCard. - * - * @return the extended AgentCard - * @throws A2AClientException if retrieving the extended agent card fails for any reason - */ - public AgentCard getExtendedAgentCard() throws A2AClientException { - return getExtendedAgentCard(null); - } - - /** - * Retrieve the extended AgentCard. - * - * @param context optional client call context for the request (may be {@code null}) - * @return the extended AgentCard - * @throws A2AClientException if retrieving the extended agent card fails for any reason - */ - public abstract AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException; - - /** - * Close the transport and release any associated resources. - */ - public abstract void close(); - - /** - * Get the error handler that should be used during streaming. - * - * @return the streaming error handler - */ - public @Nullable Consumer getStreamingErrorHandler() { - return streamingErrorHandler; - } - -} \ No newline at end of file diff --git a/client/base/src/main/java/io/a2a/client/Client.java b/client/base/src/main/java/io/a2a/client/Client.java deleted file mode 100644 index 70ed9cf18..000000000 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ /dev/null @@ -1,722 +0,0 @@ -package io.a2a.client; - -import static io.a2a.util.Assert.checkNotNullParam; - -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.A2AClientInvalidStateError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - -/** - * A client for communicating with A2A agents using the Agent2Agent Protocol. - *

- * The Client class provides the primary API for sending messages to agents, managing tasks, - * configuring push notifications, and subscribing to task updates. It abstracts the underlying - * transport protocol (JSON-RPC, gRPC, REST) and provides a consistent interface for all - * agent interactions. - *

- * Key capabilities: - *

    - *
  • Message exchange: Send messages to agents and receive responses via event consumers
  • - *
  • Task management: Query, list, and cancel tasks
  • - *
  • Streaming support: Real-time event streaming when both client and server support it
  • - *
  • Push notifications: Configure webhooks for task state changes
  • - *
  • Resubscription: Resume receiving events for ongoing tasks after disconnection
  • - *
- *

- * Resource management: Client implements {@link AutoCloseable} and should be used with - * try-with-resources to ensure proper cleanup: - *

{@code
- * AgentCard card = A2A.getAgentCard("http://localhost:9999");
- *
- * try (Client client = Client.builder(card)
- *         .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder())
- *         .addConsumer((event, agentCard) -> {
- *             if (event instanceof MessageEvent me) {
- *                 System.out.println("Response: " + me.getMessage().parts());
- *             }
- *         })
- *         .build()) {
- *
- *     // Send messages - client automatically closed when done
- *     client.sendMessage(A2A.toUserMessage("Tell me a joke"));
- * }
- * }
- *

- * Manual resource management: If not using try-with-resources, call {@link #close()} - * explicitly when done: - *

{@code
- * Client client = Client.builder(card)
- *     .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder())
- *     .addConsumer((event, agentCard) -> {
- *         // Handle events
- *     })
- *     .build();
- *
- * try {
- *     client.sendMessage(A2A.toUserMessage("Tell me a joke"));
- * } finally {
- *     client.close();  // Always close to release resources
- * }
- * }
- *

- * Event consumption model: Responses from the agent are delivered as {@link ClientEvent} - * instances to the registered consumers: - *

    - *
  • {@link MessageEvent} - contains agent response messages with content parts
  • - *
  • {@link TaskEvent} - contains complete task state (typically final state)
  • - *
  • {@link TaskUpdateEvent} - contains incremental task updates (status or artifact changes)
  • - *
- *

- * Streaming vs blocking: The client supports two communication modes: - *

    - *
  • Blocking: {@link #sendMessage} blocks until the agent completes the task
  • - *
  • Streaming: {@link #sendMessage} returns immediately, events delivered asynchronously - * to consumers as the agent processes the request
  • - *
- * The mode is determined by {@link ClientConfig#isStreaming()} AND {@link io.a2a.spec.AgentCapabilities#streaming()}. - * Both must be {@code true} for streaming mode; otherwise blocking mode is used. - *

- * Task lifecycle example: - *

{@code
- * client.addConsumer((event, card) -> {
- *     if (event instanceof TaskUpdateEvent tue) {
- *         TaskState state = tue.getTask().status().state();
- *         switch (state) {
- *             case SUBMITTED -> System.out.println("Task created");
- *             case WORKING -> System.out.println("Agent is processing...");
- *             case COMPLETED -> System.out.println("Task finished");
- *             case FAILED -> System.err.println("Task failed: " +
- *                 tue.getTask().status().message());
- *         }
- *         
- *         // Check for new artifacts
- *         if (tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent update) {
- *             Artifact artifact = update.artifact();
- *             System.out.println("New content: " + artifact.parts());
- *         }
- *     }
- * });
- * }
- *

- * Push notifications: Configure webhooks to receive task updates: - *

{@code
- * // Configure push notifications for a task
- * PushNotificationConfig pushConfig = new PushNotificationConfig(
- *     "https://my-app.com/webhooks/task-updates",
- *     Map.of("Authorization", "Bearer my-token")
- * );
- *
- * // Send message with push notifications
- * client.sendMessage(
- *     A2A.toUserMessage("Process this data"),
- *     pushConfig,
- *     null,  // metadata
- *     null   // context
- * );
- * }
- *

- * Resubscription after disconnection: - *

{@code
- * // Original request
- * client.sendMessage(A2A.toUserMessage("Long-running task"));
- * // ... client disconnects ...
- *
- * // Later, reconnect and resume receiving events
- * String taskId = "task-123";  // From original request
- * client.subscribeToTask(
- *     new TaskIdParams(taskId),
- *     List.of((event, card) -> {
- *         // Process events from where we left off
- *     }),
- *     null,  // error handler
- *     null   // context
- * );
- * }
- *

- * Thread safety: Client instances are thread-safe and can be used concurrently from - * multiple threads. Event consumers must also be thread-safe as they may be invoked concurrently - * for different tasks. - *

- * Resource management: Clients hold resources (HTTP connections, gRPC channels, etc.) - * and should be closed when no longer needed: - *

{@code
- * try (Client client = Client.builder(card)...build()) {
- *     client.sendMessage(...);
- * } // Automatically closed
- * }
- * - * @see ClientBuilder - * @see ClientEvent - * @see MessageEvent - * @see TaskEvent - * @see TaskUpdateEvent - * @see io.a2a.A2A - */ -public class Client extends AbstractClient { - - private final ClientConfig clientConfig; - private final ClientTransport clientTransport; - private AgentCard agentCard; - - /** - * Package-private constructor used by {@link ClientBuilder#build()}. - * - * @param agentCard the agent card for the target agent - * @param clientConfig the client configuration - * @param clientTransport the transport protocol implementation - * @param consumers the event consumers - * @param streamingErrorHandler the error handler for streaming scenarios - */ - Client(AgentCard agentCard, ClientConfig clientConfig, ClientTransport clientTransport, - List> consumers, @Nullable Consumer streamingErrorHandler) { - super(consumers, streamingErrorHandler); - checkNotNullParam("agentCard", agentCard); - - this.agentCard = agentCard; - this.clientConfig = clientConfig; - this.clientTransport = clientTransport; - } - - /** - * Create a new builder for constructing a client instance. - *

- * This is the primary entry point for creating clients. The builder provides a fluent - * API for configuring transports, event consumers, and client behavior. - *

- * Example: - *

{@code
-     * AgentCard card = A2A.getAgentCard("http://localhost:9999");
-     * Client client = Client.builder(card)
-     *     .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder())
-     *     .addConsumer((event, agentCard) -> processEvent(event))
-     *     .build();
-     * }
- * - * @param agentCard the agent card describing the agent to communicate with - * @return a new builder instance - * @see ClientBuilder - */ - public static ClientBuilder builder(AgentCard agentCard) { - return new ClientBuilder(agentCard); - } - - @Override - public void sendMessage(@NonNull Message request, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler, - @Nullable ClientCallContext context) throws A2AClientException { - MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(clientConfig.getPushNotificationConfig()); - - MessageSendParams messageSendParams = MessageSendParams.builder() - .message(request) - .configuration(messageSendConfiguration) - .metadata(clientConfig.getMetadata()) - .build(); - sendMessage(messageSendParams, consumers, streamingErrorHandler, context); - } - - /** - * Send a message to the agent. - *

- * This is the primary method for communicating with an agent. The behavior depends on - * whether streaming is enabled: - *

    - *
  • Streaming mode: Returns immediately, events delivered asynchronously to consumers
  • - *
  • Blocking mode: Blocks until the agent completes the task, then invokes consumers
  • - *
- * Streaming mode is active when both {@link ClientConfig#isStreaming()} AND - * {@link io.a2a.spec.AgentCapabilities#streaming()} are {@code true}. - *

- * Simple example: - *

{@code
-     * Message userMessage = A2A.toUserMessage("What's the weather?");
-     * client.sendMessage(userMessage, null, null, null);
-     * // Events delivered to consumers registered during client construction
-     * }
- *

- * With push notifications: - *

{@code
-     * PushNotificationConfig pushConfig = new PushNotificationConfig(
-     *     "https://my-app.com/webhook",
-     *     Map.of("Authorization", "Bearer token")
-     * );
-     * client.sendMessage(userMessage, pushConfig, null, null);
-     * }
- *

- * With metadata: - *

{@code
-     * Map metadata = Map.of(
-     *     "userId", "user-123",
-     *     "sessionId", "session-456"
-     * );
-     * client.sendMessage(userMessage, null, metadata, null);
-     * }
- * - * @param request the message to send (required) - * @param pushNotificationConfiguration webhook configuration for task updates (optional) - * @param metadata custom metadata to attach to the request (optional) - * @param context custom call context for request interceptors (optional) - * @throws A2AClientException if the message cannot be sent or if the agent returns an error - * @see #sendMessage(Message, List, Consumer, ClientCallContext) - * @see PushNotificationConfig - */ - @Override - public void sendMessage(@NonNull Message request, - @Nullable PushNotificationConfig pushNotificationConfiguration, - @Nullable Map metadata, - @Nullable ClientCallContext context) throws A2AClientException { - MessageSendConfiguration messageSendConfiguration = createMessageSendConfiguration(pushNotificationConfiguration); - MessageSendParams messageSendParams = MessageSendParams.builder() - .message(request) - .configuration(messageSendConfiguration) - .metadata(metadata) - .build(); - - sendMessage(messageSendParams, consumers, streamingErrorHandler, context); - } - - @Override - public void sendMessage(@NonNull MessageSendParams messageSendParams, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler, - @Nullable ClientCallContext context) throws A2AClientException { - if (! clientConfig.isStreaming() || ! agentCard.capabilities().streaming()) { - EventKind eventKind = clientTransport.sendMessage(messageSendParams, context); - ClientEvent clientEvent; - if (eventKind instanceof Task task) { - clientEvent = new TaskEvent(task); - } else { - // must be a message - clientEvent = new MessageEvent((Message) eventKind); - } - consume(clientEvent, agentCard, consumers); - } else { - ClientTaskManager tracker = new ClientTaskManager(); - Consumer overriddenErrorHandler = getOverriddenErrorHandler(streamingErrorHandler); - Consumer eventHandler = event -> { - try { - ClientEvent clientEvent = getClientEvent(event, tracker); - consume(clientEvent, agentCard, consumers); - } catch (A2AClientError e) { - overriddenErrorHandler.accept(e); - } - }; - clientTransport.sendMessageStreaming(messageSendParams, eventHandler, overriddenErrorHandler, context); - } - } - - - /** - * Retrieve a specific task by ID. - *

- * This method queries the agent for the current state of a task. It's useful for: - *

    - *
  • Checking the status of a task after disconnection
  • - *
  • Retrieving task results without subscribing to events
  • - *
  • Polling for task completion (when streaming is not available)
  • - *
- *

- * Example: - *

{@code
-     * Task task = client.getTask(new TaskQueryParams("task-123"));
-     * if (task.status().state() == TaskState.COMPLETED) {
-     *     Artifact result = task.artifact();
-     *     System.out.println("Result: " + result.parts());
-     * } else if (task.status().state() == TaskState.FAILED) {
-     *     System.err.println("Task failed: " + task.status().message());
-     * }
-     * }
- * - * @param request the task query parameters containing the task ID - * @param context custom call context for request interceptors (optional) - * @return the current task state - * @throws A2AClientException if the task is not found or if a communication error occurs - * @see TaskQueryParams - * @see Task - */ - @Override - public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException { - return clientTransport.getTask(request, context); - } - - /** - * List tasks for the current session or context. - *

- * This method retrieves multiple tasks based on filter criteria. Useful for: - *

    - *
  • Viewing all tasks in a session/context
  • - *
  • Finding tasks by state (e.g., all failed tasks)
  • - *
  • Paginating through large task lists
  • - *
- *

- * Example: - *

{@code
-     * // List all tasks for a context
-     * ListTasksParams params = new ListTasksParams(
-     *     "session-123",  // contextId
-     *     null,           // state filter (null = all states)
-     *     10,             // limit
-     *     null            // offset
-     * );
-     * ListTasksResult result = client.listTasks(params);
-     * for (Task task : result.tasks()) {
-     *     System.out.println(task.id() + ": " + task.status().state());
-     * }
-     * }
- * - * @param request the list parameters with optional filters - * @param context custom call context for request interceptors (optional) - * @return the list of tasks matching the criteria - * @throws A2AClientException if a communication error occurs - * @see ListTasksParams - * @see ListTasksResult - */ - @Override - public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { - return clientTransport.listTasks(request, context); - } - - /** - * Request cancellation of a task. - *

- * This method sends a cancellation request to the agent for the specified task. The agent - * may or may not honor the request depending on its implementation and the task's current state. - *

- * Important notes: - *

    - *
  • Cancellation is a request, not a guarantee - agents may decline or be unable to cancel
  • - *
  • Some agents don't support cancellation and will return {@link io.a2a.spec.UnsupportedOperationError}
  • - *
  • Tasks in final states (COMPLETED, FAILED, CANCELED) cannot be canceled
  • - *
  • The returned task will have state CANCELED if the cancellation succeeded
  • - *
- *

- * Example: - *

{@code
-     * try {
-     *     Task canceledTask = client.cancelTask(new TaskIdParams("task-123"));
-     *     if (canceledTask.status().state() == TaskState.CANCELED) {
-     *         System.out.println("Task successfully canceled");
-     *     }
-     * } catch (A2AClientException e) {
-     *     if (e.getCause() instanceof UnsupportedOperationError) {
-     *         System.err.println("Agent does not support cancellation");
-     *     } else if (e.getCause() instanceof TaskNotFoundError) {
-     *         System.err.println("Task not found");
-     *     }
-     * }
-     * }
- * - * @param request the task ID to cancel - * @param context custom call context for request interceptors (optional) - * @return the task with CANCELED status if successful - * @throws A2AClientException if the task cannot be canceled or if a communication error occurs - * @see TaskIdParams - * @see io.a2a.spec.UnsupportedOperationError - * @see io.a2a.spec.TaskNotFoundError - */ - @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { - return clientTransport.cancelTask(request, context); - } - - /** - * Configure push notifications for a task. - *

- * Push notifications allow your application to receive task updates via webhook instead - * of maintaining an active connection. When configured, the agent will POST events to - * the specified URL as the task progresses. - *

- * Example: - *

{@code
-     * TaskPushNotificationConfig config = new TaskPushNotificationConfig(
-     *     "task-123",
-     *     new PushNotificationConfig(
-     *         "https://my-app.com/webhooks/task-updates",
-     *         Map.of(
-     *             "Authorization", "Bearer my-webhook-secret",
-     *             "X-App-ID", "my-app"
-     *         )
-     *     )
-     * );
-     * client.createTaskPushNotificationConfiguration(config);
-     * }
- * - * @param request the push notification configuration for the task - * @param context custom call context for request interceptors (optional) - * @return the stored configuration (may include server-assigned IDs) - * @throws A2AClientException if the configuration cannot be set - * @see TaskPushNotificationConfig - * @see PushNotificationConfig - */ - @Override - public TaskPushNotificationConfig createTaskPushNotificationConfiguration( - TaskPushNotificationConfig request, @Nullable ClientCallContext context) throws A2AClientException { - return clientTransport.createTaskPushNotificationConfiguration(request, context); - } - - /** - * Retrieve the push notification configuration for a task. - *

- * Example: - *

{@code
-     * GetTaskPushNotificationConfigParams params =
-     *     new GetTaskPushNotificationConfigParams("task-123");
-     * TaskPushNotificationConfig config =
-     *     client.getTaskPushNotificationConfiguration(params);
-     * System.out.println("Webhook URL: " +
-     *     config.pushNotificationConfig().url());
-     * }
- * - * @param request the parameters specifying which task's configuration to retrieve - * @param context custom call context for request interceptors (optional) - * @return the push notification configuration for the task - * @throws A2AClientException if the configuration cannot be retrieved - * @see GetTaskPushNotificationConfigParams - */ - @Override - public TaskPushNotificationConfig getTaskPushNotificationConfiguration( - GetTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { - return clientTransport.getTaskPushNotificationConfiguration(request, context); - } - - /** - * List all push notification configurations, optionally filtered by task or context. - *

- * Example: - *

{@code
-     * // List all configurations for a context
-     * ListTaskPushNotificationConfigParams params =
-     *     new ListTaskPushNotificationConfigParams("session-123", null, 10, null);
-     * ListTaskPushNotificationConfigResult result =
-     *     client.listTaskPushNotificationConfigurations(params);
-     * for (TaskPushNotificationConfig config : result.configurations()) {
-     *     System.out.println("Task " + config.taskId() + " -> " +
-     *         config.pushNotificationConfig().url());
-     * }
-     * }
- * - * @param request the list parameters with optional filters - * @param context custom call context for request interceptors (optional) - * @return the list of push notification configurations - * @throws A2AClientException if the configurations cannot be retrieved - * @see ListTaskPushNotificationConfigParams - */ - @Override - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { - return clientTransport.listTaskPushNotificationConfigurations(request, context); - } - - /** - * Delete push notification configurations. - *

- * This method removes push notification configurations for the specified tasks or context. - * After deletion, the agent will stop sending webhook notifications for those tasks. - *

- * Example: - *

{@code
-     * // Delete configuration for a specific task
-     * DeleteTaskPushNotificationConfigParams params =
-     *     new DeleteTaskPushNotificationConfigParams(
-     *         null,           // contextId (null = not filtering by context)
-     *         List.of("task-123", "task-456")  // specific task IDs
-     *     );
-     * client.deleteTaskPushNotificationConfigurations(params);
-     * }
- * - * @param request the delete parameters specifying which configurations to remove - * @param context custom call context for request interceptors (optional) - * @throws A2AClientException if the configurations cannot be deleted - * @see DeleteTaskPushNotificationConfigParams - */ - @Override - public void deleteTaskPushNotificationConfigurations( - DeleteTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { - clientTransport.deleteTaskPushNotificationConfigurations(request, context); - } - - /** - * Subscribe to an existing task to receive remaining events. - *

- * This method is useful when a client disconnects during a long-running task and wants to - * resume receiving events without starting a new task. The agent will deliver any events - * that occurred since the original subscription. - *

- * Requirements: - *

    - *
  • Both {@link ClientConfig#isStreaming()} and {@link io.a2a.spec.AgentCapabilities#streaming()} - * must be {@code true}
  • - *
  • The task must still exist and not be in a final state (or the agent must support - * historical event replay)
  • - *
- *

- * Example: - *

{@code
-     * // Original request (client1)
-     * client1.sendMessage(A2A.toUserMessage("Analyze this dataset"));
-     * String taskId = ...; // Save task ID from TaskEvent
-     * // ... client1 disconnects ...
-     *
-     * // Later, reconnect (client2)
-     * client2.subscribeToTask(
-     *     new TaskIdParams(taskId),
-     *     List.of((event, card) -> {
-     *         if (event instanceof TaskUpdateEvent tue) {
-     *             System.out.println("Resumed - status: " +
-     *                 tue.getTask().status().state());
-     *         }
-     *     }),
-     *     throwable -> System.err.println("Subscribe error: " + throwable),
-     *     null
-     * );
-     * }
- * - * @param request the task ID to subscribe to - * @param consumers the event consumers for processing events (required) - * @param streamingErrorHandler error handler for streaming errors (optional) - * @param context custom call context for request interceptors (optional) - * @throws A2AClientException if subscription is not supported or if the task cannot be found - */ - @Override - public void subscribeToTask(@NonNull TaskIdParams request, - @NonNull List> consumers, - @Nullable Consumer streamingErrorHandler, - @Nullable ClientCallContext context) throws A2AClientException { - if (! clientConfig.isStreaming() || ! agentCard.capabilities().streaming()) { - throw new A2AClientException("Client and/or server does not support resubscription"); - } - ClientTaskManager tracker = new ClientTaskManager(); - Consumer overriddenErrorHandler = getOverriddenErrorHandler(streamingErrorHandler); - Consumer eventHandler = event -> { - try { - ClientEvent clientEvent = getClientEvent(event, tracker); - consume(clientEvent, agentCard, consumers); - } catch (A2AClientError e) { - overriddenErrorHandler.accept(e); - } - }; - clientTransport.subscribeToTask(request, eventHandler, overriddenErrorHandler, context); - } - - /** - * Retrieve the agent's extended agent card. - *

- * This method fetches the extended agent card from the agent (if the extendedAgentCard capability is supported). - * The card may have changed since - * client construction (e.g., new skills added, capabilities updated). The client's internal - * reference is updated to the newly retrieved card. - *

- * Example: - *

{@code
-     * AgentCard updatedCard = client.getExtendedAgentCard(null);
-     * System.out.println("Agent version: " + updatedCard.version());
-     * System.out.println("Skills: " + updatedCard.skills().size());
-     * }
- * - * @param context custom call context for request interceptors (optional) - * @return the agent's extended agent card - * @throws A2AClientException if the extended agent card cannot be retrieved - * @see AgentCard - */ - @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - agentCard = clientTransport.getExtendedAgentCard(context); - return agentCard; - } - - /** - * Close this client and release all associated resources. - *

- * This method closes the underlying transport (HTTP connections, gRPC channels, etc.) - * and releases any other resources held by the client. After calling this method, the - * client instance should not be used further. - *

- * Important: Always close clients when done to avoid resource leaks: - *

{@code
-     * Client client = Client.builder(card)...build();
-     * try {
-     *     client.sendMessage(...);
-     * } finally {
-     *     client.close();
-     * }
-     * // Or use try-with-resources if Client implements AutoCloseable
-     * }
- */ - @Override - public void close() { - clientTransport.close(); - } - - private ClientEvent getClientEvent(StreamingEventKind event, ClientTaskManager taskManager) throws A2AClientError { - if (event instanceof Message message) { - return new MessageEvent(message); - } else if (event instanceof Task task) { - taskManager.saveTaskEvent(task); - return new TaskEvent(taskManager.getCurrentTask()); - } else if (event instanceof TaskStatusUpdateEvent updateEvent) { - taskManager.saveTaskEvent(updateEvent); - return new TaskUpdateEvent(taskManager.getCurrentTask(), updateEvent); - } else if (event instanceof TaskArtifactUpdateEvent updateEvent) { - taskManager.saveTaskEvent(updateEvent); - return new TaskUpdateEvent(taskManager.getCurrentTask(), updateEvent); - } else { - throw new A2AClientInvalidStateError("Invalid client event"); - } - } - - private MessageSendConfiguration createMessageSendConfiguration(@Nullable PushNotificationConfig pushNotificationConfig) { - return MessageSendConfiguration.builder() - .acceptedOutputModes(clientConfig.getAcceptedOutputModes()) - .blocking(!clientConfig.isPolling()) - .historyLength(clientConfig.getHistoryLength()) - .pushNotificationConfig(pushNotificationConfig) - .build(); - } - - private @NonNull Consumer getOverriddenErrorHandler(@Nullable Consumer errorHandler) { - return e -> { - if (errorHandler != null) { - errorHandler.accept(e); - } else { - if (getStreamingErrorHandler() != null) { - getStreamingErrorHandler().accept(e); - } - } - }; - } - - private void consume(ClientEvent clientEvent, AgentCard agentCard, @NonNull List> consumers) { - for (BiConsumer consumer : consumers) { - consumer.accept(clientEvent, agentCard); - } - } -} diff --git a/client/base/src/main/java/io/a2a/client/ClientBuilder.java b/client/base/src/main/java/io/a2a/client/ClientBuilder.java deleted file mode 100644 index 81c812c91..000000000 --- a/client/base/src/main/java/io/a2a/client/ClientBuilder.java +++ /dev/null @@ -1,434 +0,0 @@ -package io.a2a.client; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.ServiceLoader.Provider; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.client.transport.spi.ClientTransportWrapper; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Builder for creating instances of {@link Client} to communicate with A2A agents. - *

- * ClientBuilder provides a fluent API for configuring and creating client instances that - * communicate with A2A agents. It handles transport negotiation, event consumer registration, - * and client configuration in a type-safe manner. - *

- * Key responsibilities: - *

    - *
  • Transport selection and negotiation between client and server capabilities
  • - *
  • Event consumer registration for processing agent responses
  • - *
  • Error handler configuration for streaming scenarios
  • - *
  • Client behavior configuration (streaming, polling, preferences)
  • - *
- *

- * Transport Selection: The builder automatically negotiates the best transport protocol - * based on the agent's {@link AgentCard} and the client's configured transports. By default, - * the server's preferred transport (first in {@link AgentCard#supportedInterfaces()}) is used. - * This can be changed by setting {@link ClientConfig#isUseClientPreference()} to {@code true}. - *

- * Typical usage pattern: - *

{@code
- * // 1. Get the agent card
- * AgentCard card = A2A.getAgentCard("http://localhost:9999");
- *
- * // 2. Build client with transport and event consumer
- * Client client = Client.builder(card)
- *     .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder())
- *     .addConsumer((event, agentCard) -> {
- *         if (event instanceof MessageEvent me) {
- *             System.out.println("Received: " + me.getMessage().parts());
- *         } else if (event instanceof TaskUpdateEvent tue) {
- *             System.out.println("Task status: " + tue.getTask().status().state());
- *         }
- *     })
- *     .build();
- *
- * // 3. Send messages
- * client.sendMessage(A2A.toUserMessage("Hello agent!"));
- * }
- *

- * Multiple transports: You can configure multiple transports for fallback: - *

{@code
- * Client client = Client.builder(card)
- *     .withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder()
- *         .channelFactory(ManagedChannelBuilder::forAddress))
- *     .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder())
- *     .clientConfig(new ClientConfig.Builder()
- *         .setUseClientPreference(true)  // Try client's preferred order
- *         .build())
- *     .build();
- * }
- *

- * Error handling: For streaming scenarios, configure an error handler to process exceptions: - *

{@code
- * Client client = Client.builder(card)
- *     .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder())
- *     .streamingErrorHandler(throwable -> {
- *         System.err.println("Stream error: " + throwable.getMessage());
- *     })
- *     .build();
- * }
- *

- * Thread safety: ClientBuilder is not thread-safe and should only be used from a single - * thread during client construction. The resulting {@link Client} instance is thread-safe. - * - * @see Client - * @see ClientConfig - * @see ClientEvent - * @see io.a2a.client.transport.spi.ClientTransport - */ -public class ClientBuilder { - - private static final Map>> transportProviderRegistry = new HashMap<>(); - private static final Map, String> transportProtocolMapping = new HashMap<>(); - private static final Logger LOGGER = LoggerFactory.getLogger(ClientBuilder.class); - - static { - ServiceLoader loader = ServiceLoader.load(ClientTransportProvider.class); - for (ClientTransportProvider transport : loader) { - transportProviderRegistry.put(transport.getTransportProtocol(), transport); - transportProtocolMapping.put(transport.getTransportProtocolClass(), transport.getTransportProtocol()); - } - } - - private final AgentCard agentCard; - - private final List> consumers = new ArrayList<>(); - private @Nullable Consumer streamErrorHandler; - private ClientConfig clientConfig = new ClientConfig.Builder().build(); - - private final Map, ClientTransportConfig> clientTransports = new LinkedHashMap<>(); - - /** - * Package-private constructor used by {@link Client#builder(AgentCard)}. - * - * @param agentCard the agent card for the agent this client will communicate with (required) - */ - ClientBuilder(@NonNull AgentCard agentCard) { - this.agentCard = agentCard; - } - - /** - * Configure a transport protocol using a builder for type-safe configuration. - *

- * Multiple transports can be configured to support fallback scenarios. The actual transport - * used is negotiated based on the agent's capabilities and the {@link ClientConfig}. - *

- * Example: - *

{@code
-     * builder.withTransport(JSONRPCTransport.class,
-     *     new JSONRPCTransportConfigBuilder()
-     *         .httpClient(customHttpClient)
-     *         .addInterceptor(loggingInterceptor));
-     * }
- * - * @param clazz the transport class to configure - * @param configBuilder the transport configuration builder - * @param the transport type - * @return this builder for method chaining - */ - public ClientBuilder withTransport(Class clazz, ClientTransportConfigBuilder, ?> configBuilder) { - return withTransport(clazz, configBuilder.build()); - } - - /** - * Configure a transport protocol with a pre-built configuration. - *

- * Multiple transports can be configured to support fallback scenarios. The actual transport - * used is negotiated based on the agent's capabilities and the {@link ClientConfig}. - *

- * Example: - *

{@code
-     * JSONRPCTransportConfig config = new JSONRPCTransportConfig(myHttpClient);
-     * builder.withTransport(JSONRPCTransport.class, config);
-     * }
- * - * @param clazz the transport class to configure - * @param config the transport configuration - * @param the transport type - * @return this builder for method chaining - */ - public ClientBuilder withTransport(Class clazz, ClientTransportConfig config) { - clientTransports.put(clazz, config); - - return this; - } - - /** - * Add a single event consumer to process events from the agent. - *

- * Consumers receive {@link ClientEvent} instances (MessageEvent, TaskEvent, TaskUpdateEvent) - * along with the agent's {@link AgentCard}. Multiple consumers can be registered and will - * be invoked in registration order. - *

- * Example: - *

{@code
-     * builder.addConsumer((event, card) -> {
-     *     if (event instanceof MessageEvent me) {
-     *         String text = me.getMessage().parts().stream()
-     *             .filter(p -> p instanceof TextPart)
-     *             .map(p -> ((TextPart) p).text())
-     *             .collect(Collectors.joining());
-     *         System.out.println("Agent: " + text);
-     *     }
-     * });
-     * }
- * - * @param consumer the event consumer to add - * @return this builder for method chaining - * @see ClientEvent - * @see MessageEvent - * @see TaskEvent - * @see TaskUpdateEvent - */ - public ClientBuilder addConsumer(BiConsumer consumer) { - this.consumers.add(consumer); - return this; - } - - /** - * Add multiple event consumers to process events from the agent. - *

- * Consumers receive {@link ClientEvent} instances and are invoked in the order they - * appear in the list. - * - * @param consumers the list of event consumers to add - * @return this builder for method chaining - * @see #addConsumer(BiConsumer) - */ - public ClientBuilder addConsumers(List> consumers) { - this.consumers.addAll(consumers); - return this; - } - - /** - * Configure an error handler for streaming scenarios. - *

- * This handler is invoked when errors occur during streaming event consumption. It's only - * applicable when the client and agent both support streaming. For non-streaming scenarios, - * errors are thrown directly as {@link A2AClientException}. - *

- * Example: - *

{@code
-     * builder.streamingErrorHandler(throwable -> {
-     *     if (throwable instanceof A2AClientException e) {
-     *         log.error("A2A error: " + e.getMessage(), e);
-     *     } else {
-     *         log.error("Unexpected error: " + throwable.getMessage(), throwable);
-     *     }
-     * });
-     * }
- * - * @param streamErrorHandler the error handler for streaming errors - * @return this builder for method chaining - */ - public ClientBuilder streamingErrorHandler(Consumer streamErrorHandler) { - this.streamErrorHandler = streamErrorHandler; - return this; - } - - /** - * Configure client behavior such as streaming mode, polling, and transport preference. - *

- * The configuration controls how the client communicates with the agent: - *

    - *
  • Streaming vs blocking mode
  • - *
  • Polling for updates vs receiving events
  • - *
  • Client vs server transport preference
  • - *
  • Output modes, history length, and metadata
  • - *
- *

- * Example: - *

{@code
-     * ClientConfig config = new ClientConfig.Builder()
-     *     .setStreaming(true)  // Enable streaming if server supports it
-     *     .setUseClientPreference(true)  // Use client's transport order
-     *     .setHistoryLength(10)  // Request last 10 messages of context
-     *     .build();
-     * builder.clientConfig(config);
-     * }
- * - * @param clientConfig the client configuration - * @return this builder for method chaining - * @see ClientConfig - */ - public ClientBuilder clientConfig(@NonNull ClientConfig clientConfig) { - this.clientConfig = clientConfig; - return this; - } - - /** - * Build the configured {@link Client} instance. - *

- * This method performs transport negotiation between the client's configured transports - * and the agent's {@link AgentCard#supportedInterfaces()}. The selection algorithm: - *

    - *
  1. If {@link ClientConfig#isUseClientPreference()} is {@code true}, iterate through - * client transports in registration order and select the first one the server supports
  2. - *
  3. Otherwise, iterate through server interfaces in preference order (first entry - * in {@link AgentCard#supportedInterfaces()}) and select the first one the client supports
  4. - *
- *

- * Important: At least one transport must be configured via {@link #withTransport}, - * otherwise this method throws {@link A2AClientException}. - * - * @return the configured client instance - * @throws A2AClientException if no compatible transport is found or if transport configuration is missing - */ - public Client build() throws A2AClientException { - if (this.clientConfig == null) { - this.clientConfig = new ClientConfig.Builder().build(); - } - - ClientTransport clientTransport = buildClientTransport(); - - return new Client(agentCard, clientConfig, clientTransport, consumers, streamErrorHandler); - } - - @SuppressWarnings("unchecked") - private ClientTransport buildClientTransport() throws A2AClientException { - // Get the preferred transport - AgentInterface agentInterface = findBestClientTransport(); - - // Get the transport provider associated with the protocol - ClientTransportProvider clientTransportProvider = transportProviderRegistry.get(agentInterface.protocolBinding()); - if (clientTransportProvider == null) { - throw new A2AClientException("No client available for " + agentInterface.protocolBinding()); - } - Class transportProtocolClass = clientTransportProvider.getTransportProtocolClass(); - - // Retrieve the configuration associated with the preferred transport - ClientTransportConfig clientTransportConfig = clientTransports.get(transportProtocolClass); - - if (clientTransportConfig == null) { - throw new A2AClientException("Missing required TransportConfig for " + agentInterface.protocolBinding()); - } - - return wrap(clientTransportProvider.create(clientTransportConfig, agentCard, agentInterface), clientTransportConfig); - } - - private Map getServerPreferredTransports() throws A2AClientException { - Map serverPreferredTransports = new LinkedHashMap<>(); - if(agentCard.supportedInterfaces() == null || agentCard.supportedInterfaces().isEmpty()) { - throw new A2AClientException("No server interface available in the AgentCard"); - } - for (AgentInterface agentInterface : agentCard.supportedInterfaces()) { - serverPreferredTransports.putIfAbsent(agentInterface.protocolBinding(), agentInterface.url()); - } - return serverPreferredTransports; - } - - private List getClientPreferredTransports() { - List supportedClientTransports = new ArrayList<>(); - - if (clientTransports.isEmpty()) { - // default to JSONRPC if not specified - supportedClientTransports.add(TransportProtocol.JSONRPC.asString()); - } else { - clientTransports.forEach((aClass, clientTransportConfig) -> supportedClientTransports.add(transportProtocolMapping.get(aClass))); - } - return supportedClientTransports; - } - - private AgentInterface findBestClientTransport() throws A2AClientException { - // Retrieve transport supported by the A2A server - Map serverPreferredTransports = getServerPreferredTransports(); - - // Retrieve transport configured for this client (using withTransport methods) - List clientPreferredTransports = getClientPreferredTransports(); - - String transportProtocol = null; - String transportUrl = null; - if (clientConfig.isUseClientPreference()) { - for (String clientPreferredTransport : clientPreferredTransports) { - if (serverPreferredTransports.containsKey(clientPreferredTransport)) { - transportProtocol = clientPreferredTransport; - transportUrl = serverPreferredTransports.get(transportProtocol); - break; - } - } - } else { - for (Map.Entry transport : serverPreferredTransports.entrySet()) { - if (clientPreferredTransports.contains(transport.getKey())) { - transportProtocol = transport.getKey(); - transportUrl = transport.getValue(); - break; - } - } - } - if (transportProtocol == null || transportUrl == null) { - throw new A2AClientException("No compatible transport found"); - } - if (!transportProviderRegistry.containsKey(transportProtocol)) { - throw new A2AClientException("No client available for " + transportProtocol); - } - - return new AgentInterface(transportProtocol, transportUrl); - } - - /** - * Wraps the transport with all available transport wrappers discovered via ServiceLoader. - * Wrappers are applied in reverse priority order (lowest priority first) to build a stack - * where the highest priority wrapper is the outermost layer. - * - * @param transport the base transport to wrap - * @param clientTransportConfig the transport configuration - * @return the wrapped transport (or original if no wrappers are available/applicable) - */ - private ClientTransport wrap(ClientTransport transport, ClientTransportConfig clientTransportConfig) { - ServiceLoader wrapperLoader = ServiceLoader.load(ClientTransportWrapper.class); - - // Collect all wrappers, sort by priority, then reverse for stack application - List wrappers = wrapperLoader.stream().map(Provider::get) - .sorted() - .collect(Collectors.toList()); - - if (wrappers.isEmpty()) { - LOGGER.debug("No client transport wrappers found via ServiceLoader"); - return transport; - } - LOGGER.debug(wrappers.size() + " client transport wrappers found via ServiceLoader"); - - // Reverse to apply lowest priority first (building stack with highest priority outermost) - java.util.Collections.reverse(wrappers); - - // Apply wrappers to build stack - ClientTransport wrapped = transport; - for (ClientTransportWrapper wrapper : wrappers) { - try { - ClientTransport newWrapped = wrapper.wrap(wrapped, clientTransportConfig); - if (newWrapped != wrapped) { - LOGGER.debug("Applied transport wrapper: {} (priority: {})", - wrapper.getClass().getName(), wrapper.priority()); - } - wrapped = newWrapped; - } catch (Exception e) { - LOGGER.warn("Failed to apply transport wrapper {}: {}", - wrapper.getClass().getName(), e.getMessage(), e); - } - } - - return wrapped; - } -} diff --git a/client/base/src/main/java/io/a2a/client/ClientEvent.java b/client/base/src/main/java/io/a2a/client/ClientEvent.java deleted file mode 100644 index 2275a7f2e..000000000 --- a/client/base/src/main/java/io/a2a/client/ClientEvent.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.a2a.client; - -/** - * A sealed interface representing events received by an A2A client from an agent. - *

- * ClientEvent is the base type for all events that clients receive during agent interactions. - * The sealed interface ensures type safety by restricting implementations to three known subtypes: - *

    - *
  • {@link MessageEvent} - contains complete messages with content parts
  • - *
  • {@link TaskEvent} - contains complete task state, typically final states
  • - *
  • {@link TaskUpdateEvent} - contains incremental task updates (status or artifact changes)
  • - *
- *

- * Event flow: When a client sends a message to an agent, the agent's response is delivered - * as a stream of ClientEvent instances to registered event consumers. The event type and sequence - * depend on the agent's capabilities and the task's lifecycle: - *

- * Simple blocking response: - *

- * User → Agent
- * Agent → MessageEvent (contains agent's text response)
- * 
- *

- * Streaming task execution: - *

- * User → Agent
- * Agent → TaskEvent (SUBMITTED)
- * Agent → TaskUpdateEvent (WORKING)
- * Agent → TaskUpdateEvent (artifact update with partial results)
- * Agent → TaskUpdateEvent (artifact update with more results)
- * Agent → TaskUpdateEvent (COMPLETED)
- * 
- *

- * Typical usage pattern: - *

{@code
- * client.addConsumer((event, agentCard) -> {
- *     switch (event) {
- *         case MessageEvent me -> {
- *             // Simple message response
- *             System.out.println("Response: " + me.getMessage().parts());
- *         }
- *         case TaskEvent te -> {
- *             // Complete task state (usually final)
- *             Task task = te.getTask();
- *             System.out.println("Task " + task.id() + ": " + task.status().state());
- *         }
- *         case TaskUpdateEvent tue -> {
- *             // Incremental update
- *             Task currentTask = tue.getTask();
- *             UpdateEvent update = tue.getUpdateEvent();
- *
- *             if (update instanceof TaskStatusUpdateEvent statusUpdate) {
- *                 System.out.println("Status changed to: " +
- *                     currentTask.status().state());
- *             } else if (update instanceof TaskArtifactUpdateEvent artifactUpdate) {
- *                 System.out.println("New content: " +
- *                     artifactUpdate.artifact().parts());
- *             }
- *         }
- *     }
- * });
- * }
- *

- * Legacy vs current protocol: In older versions of the A2A protocol, agents returned - * {@link MessageEvent} for simple responses and {@link TaskEvent} for task-based responses. - * The current protocol (v1.0+) uses {@link TaskUpdateEvent} for streaming updates during - * task execution, providing finer-grained visibility into agent progress. - * - * @see MessageEvent - * @see TaskEvent - * @see TaskUpdateEvent - * @see ClientBuilder#addConsumer(java.util.function.BiConsumer) - */ -public sealed interface ClientEvent permits MessageEvent, TaskEvent, TaskUpdateEvent { -} diff --git a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java b/client/base/src/main/java/io/a2a/client/ClientTaskManager.java deleted file mode 100644 index 0e49fc4f7..000000000 --- a/client/base/src/main/java/io/a2a/client/ClientTaskManager.java +++ /dev/null @@ -1,136 +0,0 @@ -package io.a2a.client; - -import static io.a2a.util.Utils.appendArtifactToTask; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientInvalidArgsError; -import io.a2a.spec.A2AClientInvalidStateError; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.jspecify.annotations.Nullable; - -/** - * Helps manage a task's lifecycle during the execution of a request. - * Responsible for retrieving, saving, and updating the task based on - * events received from the agent. - */ -public class ClientTaskManager { - - private @Nullable Task currentTask; - private @Nullable String taskId; - private @Nullable String contextId; - - public ClientTaskManager() { - this.currentTask = null; - this.taskId = null; - this.contextId = null; - } - - public Task getCurrentTask() throws A2AClientInvalidStateError { - if (currentTask == null) { - throw new A2AClientInvalidStateError("No current task"); - } - return currentTask; - } - - public Task saveTaskEvent(Task task) throws A2AClientInvalidArgsError { - if (currentTask != null) { - throw new A2AClientInvalidArgsError("Task is already set, create new manager for new tasks."); - } - saveTask(task); - return task; - } - - public Task saveTaskEvent(TaskStatusUpdateEvent taskStatusUpdateEvent) throws A2AClientError { - if (taskId == null) { - taskId = taskStatusUpdateEvent.taskId(); - } - if (contextId == null) { - contextId = taskStatusUpdateEvent.contextId(); - } - Task task = currentTask; - if (task == null) { - task = Task.builder() - .status(new TaskStatus(TaskState.UNRECOGNIZED)) - .id(taskId) - .contextId(contextId == null ? "" : contextId) - .build(); - } - - Task.Builder taskBuilder = Task.builder(task); - if (taskStatusUpdateEvent.status().message() != null) { - if (task.history() == null) { - taskBuilder.history(taskStatusUpdateEvent.status().message()); - } else { - List history = new ArrayList<>(task.history()); - history.add(taskStatusUpdateEvent.status().message()); - taskBuilder.history(history); - } - } - if (taskStatusUpdateEvent.metadata() != null) { - Map newMetadata = task.metadata() != null ? new HashMap<>(task.metadata()) : new HashMap<>(); - newMetadata.putAll(taskStatusUpdateEvent.metadata()); - taskBuilder.metadata(newMetadata); - } - taskBuilder.status(taskStatusUpdateEvent.status()); - currentTask = taskBuilder.build(); - return currentTask; - } - - public Task saveTaskEvent(TaskArtifactUpdateEvent taskArtifactUpdateEvent) { - if (taskId == null) { - taskId = taskArtifactUpdateEvent.taskId(); - } - if (contextId == null) { - contextId = taskArtifactUpdateEvent.contextId(); - } - Task task = currentTask; - if (task == null) { - task = Task.builder() - .status(new TaskStatus(TaskState.UNRECOGNIZED)) - .id(taskId) - .contextId(contextId == null ? "" : contextId) - .build(); - } - currentTask = appendArtifactToTask(task, taskArtifactUpdateEvent, taskId); - return currentTask; - } - - /** - * Update a task by adding a message to its history. If the task has a message in its current status, - * that message is moved to the history first. - * - * @param message the new message to add to the history - * @param task the task to update - * @return the updated task - */ - public Task updateWithMessage(Message message, Task task) { - Task.Builder taskBuilder = Task.builder(task); - List history = new ArrayList<>(task.history()); - if (task.status().message() != null) { - history.add(task.status().message()); - taskBuilder.status(new TaskStatus(task.status().state(), null, task.status().timestamp())); - } - history.add(message); - taskBuilder.history(history); - currentTask = taskBuilder.build(); - return currentTask; - } - - private void saveTask(Task task) { - currentTask = task; - if (taskId == null) { - taskId = currentTask.id(); - contextId = currentTask.contextId(); - } - } -} \ No newline at end of file diff --git a/client/base/src/main/java/io/a2a/client/MessageEvent.java b/client/base/src/main/java/io/a2a/client/MessageEvent.java deleted file mode 100644 index 1db7b39fd..000000000 --- a/client/base/src/main/java/io/a2a/client/MessageEvent.java +++ /dev/null @@ -1,92 +0,0 @@ -package io.a2a.client; - -import io.a2a.spec.Message; - -/** - * A client event containing an agent's message response. - *

- * MessageEvent represents a complete message from the agent, typically containing text, images, - * or other content parts. This event type is used in two scenarios: - *

    - *
  1. Simple blocking responses: When the agent completes a request immediately and - * returns a message without task tracking
  2. - *
  3. Legacy protocol support: Older agents may return messages instead of task updates
  4. - *
- *

- * Example usage: - *

{@code
- * client.addConsumer((event, agentCard) -> {
- *     if (event instanceof MessageEvent me) {
- *         Message msg = me.getMessage();
- *         
- *         // Extract text content
- *         String text = msg.parts().stream()
- *             .filter(p -> p instanceof TextPart)
- *             .map(p -> ((TextPart) p).text())
- *             .collect(Collectors.joining());
- *         
- *         System.out.println("Agent response: " + text);
- *         
- *         // Check for images
- *         msg.parts().stream()
- *             .filter(p -> p instanceof ImagePart)
- *             .forEach(p -> System.out.println("Image: " + ((ImagePart) p).url()));
- *     }
- * });
- * }
- *

- * Message structure: The contained {@link Message} includes: - *

    - *
  • role: AGENT (indicating it's from the agent)
  • - *
  • parts: List of content parts (text, images, files, etc.)
  • - *
  • contextId: Optional session identifier
  • - *
  • taskId: Optional associated task ID
  • - *
  • metadata: Optional custom metadata from the agent
  • - *
- *

- * Streaming vs blocking: In streaming mode with task tracking, you're more likely to - * receive {@link TaskUpdateEvent} instances instead of MessageEvent. MessageEvent is primarily - * used for simple, synchronous request-response interactions. - * - * @see ClientEvent - * @see Message - * @see io.a2a.spec.Part - * @see io.a2a.spec.TextPart - */ -public final class MessageEvent implements ClientEvent { - - private final Message message; - - /** - * Create a message event. - * - * @param message the message received from the agent (required) - */ - public MessageEvent(Message message) { - this.message = message; - } - - /** - * Get the message contained in this event. - * - * @return the agent's message - */ - public Message getMessage() { - return message; - } - - @Override - public String toString() { - String messageAsString = "{" - + "role=" + message.role() - + ", parts=" + message.parts() - + ", messageId=" + message.messageId() - + ", contextId=" + message.contextId() - + ", taskId=" + message.taskId() - + ", metadata=" + message.metadata() - + ", kind=" + message.kind() - + ", referenceTaskIds=" + message.referenceTaskIds() - + ", extensions=" + message.extensions() + '}'; - return "MessageEvent{" + "message=" + messageAsString + '}'; - } -} diff --git a/client/base/src/main/java/io/a2a/client/TaskEvent.java b/client/base/src/main/java/io/a2a/client/TaskEvent.java deleted file mode 100644 index 4da4ef04f..000000000 --- a/client/base/src/main/java/io/a2a/client/TaskEvent.java +++ /dev/null @@ -1,101 +0,0 @@ -package io.a2a.client; - -import static io.a2a.util.Assert.checkNotNullParam; - -import io.a2a.spec.Task; - -/** - * A client event containing the complete state of a task. - *

- * TaskEvent represents a snapshot of a task's full state at a point in time. This event type - * is typically received in two scenarios: - *

    - *
  1. Final task state: When a task reaches a terminal state (COMPLETED, FAILED, CANCELED), - * the agent may send a TaskEvent with the complete final state
  2. - *
  3. Non-streaming mode: When streaming is disabled, the client receives a single - * TaskEvent containing the final result after the agent completes processing
  4. - *
- *

- * Contrast with TaskUpdateEvent: While {@link TaskUpdateEvent} provides incremental - * updates during task execution (status changes, new artifacts), TaskEvent provides the - * complete task state in a single event. - *

- * Example usage: - *

{@code
- * client.addConsumer((event, agentCard) -> {
- *     if (event instanceof TaskEvent te) {
- *         Task task = te.getTask();
- *         
- *         // Check task state
- *         TaskState state = task.status().state();
- *         switch (state) {
- *             case COMPLETED -> {
- *                 // Task finished successfully
- *                 if (task.artifact() != null) {
- *                     System.out.println("Result: " + task.artifact().parts());
- *                 }
- *             }
- *             case FAILED -> {
- *                 // Task failed
- *                 String error = task.status().message();
- *                 System.err.println("Task failed: " + error);
- *             }
- *             case CANCELED -> {
- *                 System.out.println("Task was canceled");
- *             }
- *             default -> {
- *                 System.out.println("Task in state: " + state);
- *             }
- *         }
- *     }
- * });
- * }
- *

- * Task contents: The contained {@link Task} includes: - *

    - *
  • id: Unique task identifier
  • - *
  • status: Current state (SUBMITTED, WORKING, COMPLETED, FAILED, CANCELED, etc.)
  • - *
  • artifact: Task results (if available)
  • - *
  • contextId: Associated session/context identifier
  • - *
  • metadata: Custom task metadata
  • - *
  • history: Optional state transition history
  • - *
- *

- * Terminal states: When a task reaches a final state, no further updates will be - * received for that task: - *

    - *
  • COMPLETED - task finished successfully
  • - *
  • FAILED - task encountered an error
  • - *
  • CANCELED - task was canceled by user or system
  • - *
  • REJECTED - task was rejected (e.g., authorization failure)
  • - *
- * - * @see ClientEvent - * @see Task - * @see TaskUpdateEvent - * @see io.a2a.spec.TaskState - * @see io.a2a.spec.TaskStatus - */ -public final class TaskEvent implements ClientEvent { - - private final Task task; - - /** - * Create a task event. - * - * @param task the task state received from the agent (required) - */ - public TaskEvent(Task task) { - checkNotNullParam("task", task); - this.task = task; - } - - /** - * Get the task contained in this event. - * - * @return the complete task state - */ - public Task getTask() { - return task; - } -} diff --git a/client/base/src/main/java/io/a2a/client/TaskUpdateEvent.java b/client/base/src/main/java/io/a2a/client/TaskUpdateEvent.java deleted file mode 100644 index e9efe2404..000000000 --- a/client/base/src/main/java/io/a2a/client/TaskUpdateEvent.java +++ /dev/null @@ -1,154 +0,0 @@ -package io.a2a.client; - -import static io.a2a.util.Assert.checkNotNullParam; - -import io.a2a.spec.Task; -import io.a2a.spec.UpdateEvent; - -/** - * A client event containing an incremental update to a task. - *

- * TaskUpdateEvent represents a change to a task's state during execution. It provides both - * the current complete task state and the specific update that triggered this event. This - * event type is the primary mechanism for tracking task progress in streaming scenarios. - *

- * Two types of updates: - *

    - *
  • {@link io.a2a.spec.TaskStatusUpdateEvent} - task state changed (e.g., SUBMITTED → WORKING → COMPLETED)
  • - *
  • {@link io.a2a.spec.TaskArtifactUpdateEvent} - new content/results available
  • - *
- *

- * Streaming task lifecycle example: - *

{@code
- * client.sendMessage(A2A.toUserMessage("Summarize this document"));
- *
- * // Client receives sequence of TaskUpdateEvents:
- * 1. TaskUpdateEvent(task=Task[status=SUBMITTED], updateEvent=TaskStatusUpdateEvent)
- * 2. TaskUpdateEvent(task=Task[status=WORKING], updateEvent=TaskStatusUpdateEvent)
- * 3. TaskUpdateEvent(task=Task[status=WORKING, artifact=[partial]], updateEvent=TaskArtifactUpdateEvent)
- * 4. TaskUpdateEvent(task=Task[status=WORKING, artifact=[more content]], updateEvent=TaskArtifactUpdateEvent)
- * 5. TaskUpdateEvent(task=Task[status=COMPLETED, artifact=[final]], updateEvent=TaskStatusUpdateEvent)
- * }
- *

- * Example usage - tracking progress: - *

{@code
- * client.addConsumer((event, agentCard) -> {
- *     if (event instanceof TaskUpdateEvent tue) {
- *         Task currentTask = tue.getTask();
- *         UpdateEvent update = tue.getUpdateEvent();
- *         
- *         // Handle status changes
- *         if (update instanceof TaskStatusUpdateEvent statusUpdate) {
- *             TaskState newState = currentTask.status().state();
- *             System.out.println("Task " + currentTask.id() + " → " + newState);
- *             
- *             if (newState == TaskState.COMPLETED) {
- *                 System.out.println("Final result: " +
- *                     currentTask.artifact().parts());
- *             } else if (newState == TaskState.FAILED) {
- *                 System.err.println("Error: " +
- *                     currentTask.status().message());
- *             }
- *         }
- *         
- *         // Handle new content
- *         if (update instanceof TaskArtifactUpdateEvent artifactUpdate) {
- *             Artifact newContent = artifactUpdate.artifact();
- *             System.out.println("New content received: " + newContent.parts());
- *             
- *             // For streaming text generation
- *             newContent.parts().stream()
- *                 .filter(p -> p instanceof TextPart)
- *                 .map(p -> ((TextPart) p).text())
- *                 .forEach(System.out::print);  // Print incrementally
- *         }
- *     }
- * });
- * }
- *

- * Reconstructing complete state: The {@link #getTask()} method returns the task with - * all updates applied up to this point. The client automatically maintains the complete - * task state by merging updates, so consumers don't need to manually track changes: - *

{@code
- * // Each TaskUpdateEvent contains the fully updated task
- * TaskUpdateEvent event1 // task has status=WORKING, artifact=null
- * TaskUpdateEvent event2 // task has status=WORKING, artifact=[chunk1]
- * TaskUpdateEvent event3 // task has status=WORKING, artifact=[chunk1, chunk2]
- * TaskUpdateEvent event4 // task has status=COMPLETED, artifact=[chunk1, chunk2, final]
- * }
- *

- * Artifact updates: When {@link io.a2a.spec.TaskArtifactUpdateEvent} is received, - * the artifact may be: - *

    - *
  • Incremental: New parts appended to existing artifact (common for streaming text)
  • - *
  • Replacement: Entire artifact replaced (less common)
  • - *
- * The {@link #getTask()} always reflects the current complete artifact state. - *

- * Status transitions: Common task state transitions: - *

- * SUBMITTED → WORKING → COMPLETED
- * SUBMITTED → WORKING → FAILED
- * SUBMITTED → WORKING → CANCELED
- * SUBMITTED → AUTH_REQUIRED → (waiting for auth) → WORKING → COMPLETED
- * 
- * - * @see ClientEvent - * @see Task - * @see io.a2a.spec.UpdateEvent - * @see io.a2a.spec.TaskStatusUpdateEvent - * @see io.a2a.spec.TaskArtifactUpdateEvent - * @see io.a2a.spec.TaskState - */ -public final class TaskUpdateEvent implements ClientEvent { - - private final Task task; - private final UpdateEvent updateEvent; - - /** - * Create a task update event. - *

- * This constructor is typically called internally by the client framework when processing - * update events from the agent. The {@code task} parameter contains the complete current - * state with all updates applied, while {@code updateEvent} contains the specific change - * that triggered this event. - * - * @param task the current complete task state with all updates applied (required) - * @param updateEvent the specific update that triggered this event (required) - */ - public TaskUpdateEvent(Task task, UpdateEvent updateEvent) { - checkNotNullParam("task", task); - checkNotNullParam("updateEvent", updateEvent); - this.task = task; - this.updateEvent = updateEvent; - } - - /** - * Get the current complete task state. - *

- * The returned task reflects all updates received up to this point, including the - * update contained in this event. Consumers can use this method to access the - * complete current state without manually tracking changes. - * - * @return the task with all updates applied - */ - public Task getTask() { - return task; - } - - /** - * Get the specific update that triggered this event. - *

- * This will be either: - *

    - *
  • {@link io.a2a.spec.TaskStatusUpdateEvent} - indicates a state transition
  • - *
  • {@link io.a2a.spec.TaskArtifactUpdateEvent} - indicates new content available
  • - *
- * - * @return the update event - */ - public UpdateEvent getUpdateEvent() { - return updateEvent; - } - -} diff --git a/client/base/src/main/java/io/a2a/client/config/ClientConfig.java b/client/base/src/main/java/io/a2a/client/config/ClientConfig.java deleted file mode 100644 index d9ffd7e6e..000000000 --- a/client/base/src/main/java/io/a2a/client/config/ClientConfig.java +++ /dev/null @@ -1,410 +0,0 @@ -package io.a2a.client.config; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.spec.PushNotificationConfig; -import org.jspecify.annotations.Nullable; - -/** - * Configuration for controlling A2A client behavior and communication preferences. - *

- * ClientConfig defines how the client communicates with agents, including streaming mode, - * transport preference, output modes, and request metadata. The configuration is immutable - * and constructed using the {@link Builder} pattern. - *

- * Key configuration options: - *

    - *
  • Streaming: Enable/disable real-time event streaming (default: true)
  • - *
  • Polling: Use polling instead of blocking for updates (default: false)
  • - *
  • Transport preference: Client vs server transport priority (default: server preference)
  • - *
  • Output modes: Acceptable content types (text, audio, image, etc.)
  • - *
  • History length: Number of previous messages to include as context
  • - *
  • Push notifications: Default webhook configuration for task updates
  • - *
  • Metadata: Custom metadata attached to all requests
  • - *
- *

- * Streaming mode: Controls whether the client uses streaming or blocking communication. - * Streaming mode requires both the client configuration AND the agent's capabilities to support it: - *

{@code
- * // Enable streaming (if agent also supports it)
- * ClientConfig config = new ClientConfig.Builder()
- *     .setStreaming(true)
- *     .build();
- *
- * // Actual mode = config.streaming && agentCard.capabilities().streaming()
- * }
- * When streaming is enabled and supported, the client receives events asynchronously as the - * agent processes the request. When disabled, the client blocks until the task completes. - *

- * Transport preference: Controls which transport protocol is selected when multiple - * options are available: - *

{@code
- * // Default: Use server's preferred transport (first in AgentCard.supportedInterfaces)
- * ClientConfig serverPref = new ClientConfig.Builder()
- *     .setUseClientPreference(false)
- *     .build();
- *
- * // Use client's preferred transport (order of withTransport() calls)
- * ClientConfig clientPref = new ClientConfig.Builder()
- *     .setUseClientPreference(true)
- *     .build();
- *
- * Client client = Client.builder(card)
- *     .withTransport(GrpcTransport.class, grpcConfig)      // Client preference 1
- *     .withTransport(JSONRPCTransport.class, jsonConfig)   // Client preference 2
- *     .clientConfig(clientPref)
- *     .build();
- * // With useClientPreference=true, tries gRPC first, then JSON-RPC
- * // With useClientPreference=false, uses server's order from AgentCard
- * }
- *

- * Output modes: Specify which content types the client can handle: - *

{@code
- * ClientConfig config = new ClientConfig.Builder()
- *     .setAcceptedOutputModes(List.of("text", "image", "audio"))
- *     .build();
- * // Agent will only return text, image, or audio content
- * }
- *

- * Conversation history: Request previous messages as context: - *

{@code
- * ClientConfig config = new ClientConfig.Builder()
- *     .setHistoryLength(10)  // Include last 10 messages
- *     .build();
- * }
- * This is useful for maintaining conversation context across multiple requests in the same session. - *

- * Push notifications: Configure default webhook for all task updates: - *

{@code
- * PushNotificationConfig pushConfig = new PushNotificationConfig(
- *     "https://my-app.com/webhooks/tasks",
- *     Map.of("Authorization", "Bearer my-token")
- * );
- * ClientConfig config = new ClientConfig.Builder()
- *     .setPushNotificationConfig(pushConfig)
- *     .build();
- * // All sendMessage() calls will use this webhook config
- * }
- *

- * Custom metadata: Attach metadata to all requests: - *

{@code
- * Map metadata = Map.of(
- *     "userId", "user-123",
- *     "sessionId", "session-456",
- *     "clientVersion", "1.0.0"
- * );
- * ClientConfig config = new ClientConfig.Builder()
- *     .setMetadata(metadata)
- *     .build();
- * // Metadata is included in every message sent
- * }
- *

- * Complete example: - *

{@code
- * ClientConfig config = new ClientConfig.Builder()
- *     .setStreaming(true)                         // Enable streaming
- *     .setUseClientPreference(true)               // Use client transport order
- *     .setAcceptedOutputModes(List.of("text"))    // Text responses only
- *     .setHistoryLength(5)                        // Last 5 messages as context
- *     .setMetadata(Map.of("userId", "user-123"))  // Custom metadata
- *     .build();
- *
- * Client client = Client.builder(agentCard)
- *     .clientConfig(config)
- *     .withTransport(JSONRPCTransport.class, transportConfig)
- *     .build();
- * }
- *

- * Default values: - *

    - *
  • streaming: {@code true}
  • - *
  • polling: {@code false}
  • - *
  • useClientPreference: {@code false} (server preference)
  • - *
  • acceptedOutputModes: empty list (accept all)
  • - *
  • historyLength: {@code null} (no history)
  • - *
  • pushNotificationConfig: {@code null} (no push notifications)
  • - *
  • metadata: empty map
  • - *
- *

- * Thread safety: ClientConfig is immutable and thread-safe. Multiple clients can - * share the same configuration instance. - * - * @see io.a2a.client.Client - * @see io.a2a.client.ClientBuilder - * @see PushNotificationConfig - */ -public class ClientConfig { - - private final Boolean streaming; - private final Boolean polling; - private final Boolean useClientPreference; - private final List acceptedOutputModes; - private final @Nullable PushNotificationConfig pushNotificationConfig; - private final @Nullable Integer historyLength; - private final Map metadata; - - private ClientConfig(Builder builder) { - this.streaming = builder.streaming == null ? true : builder.streaming; - this.polling = builder.polling == null ? false : builder.polling; - this.useClientPreference = builder.useClientPreference == null ? false : builder.useClientPreference; - this.acceptedOutputModes = builder.acceptedOutputModes; - this.pushNotificationConfig = builder.pushNotificationConfig; - this.historyLength = builder.historyLength; - this.metadata = builder.metadata; - } - - /** - * Check if streaming mode is enabled. - *

- * Note: Actual streaming requires both this configuration AND agent support - * ({@link io.a2a.spec.AgentCapabilities#streaming()}). - * - * @return {@code true} if streaming is enabled (default) - */ - public boolean isStreaming() { - return streaming; - } - - /** - * Check if polling mode is enabled for task updates. - *

- * When polling is enabled, the client can poll for task status updates instead of - * blocking or streaming. This is useful for asynchronous workflows where the client - * doesn't need immediate results. - * - * @return {@code true} if polling is enabled, {@code false} by default - */ - public boolean isPolling() { - return polling; - } - - /** - * Check if client transport preference is enabled. - *

- * When {@code true}, the client iterates through its configured transports (in the order - * they were added via {@link io.a2a.client.ClientBuilder#withTransport}) and selects the first one - * the agent supports. - *

- * When {@code false} (default), the agent's preferred transport is used (first entry - * in {@link io.a2a.spec.AgentCard#supportedInterfaces()}). - * - * @return {@code true} if using client preference, {@code false} for server preference (default) - */ - public boolean isUseClientPreference() { - return useClientPreference; - } - - /** - * Get the list of accepted output modes. - *

- * This list specifies which content types the client can handle (e.g., "text", "audio", - * "image", "video"). An empty list means all modes are accepted. - *

- * The agent will only return content in the specified modes. For example, if only "text" - * is specified, the agent won't return images or audio. - * - * @return the list of accepted output modes (never null, but may be empty) - */ - public List getAcceptedOutputModes() { - return acceptedOutputModes; - } - - /** - * Get the default push notification configuration. - *

- * If set, this webhook configuration will be used for all sendMessage - * calls unless overridden with a different configuration. - * - * @return the push notification config, or {@code null} if not configured - * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.PushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) - */ - public @Nullable PushNotificationConfig getPushNotificationConfig() { - return pushNotificationConfig; - } - - /** - * Get the conversation history length. - *

- * This value specifies how many previous messages should be included as context - * when sending a new message. For example, a value of 10 means the agent receives - * the last 10 messages in the conversation for context. - * - * @return the history length, or {@code null} if not configured (no history) - */ - public @Nullable Integer getHistoryLength() { - return historyLength; - } - - /** - * Get the custom metadata attached to all requests. - *

- * This metadata is included in every message sent by the client. It can contain - * user IDs, session identifiers, client version, or any other custom data. - * - * @return the metadata map (never null, but may be empty) - */ - public Map getMetadata() { - return metadata; - } - - /** - * Create a new builder for constructing ClientConfig instances. - * - * @return a new builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for creating {@link ClientConfig} instances. - *

- * All configuration options have sensible defaults and are optional. Use this builder - * to override specific settings as needed. - *

- * Example: - *

{@code
-     * ClientConfig config = new ClientConfig.Builder()
-     *     .setStreaming(true)
-     *     .setHistoryLength(10)
-     *     .build();
-     * }
- */ - public static class Builder { - private @Nullable Boolean streaming; - private @Nullable Boolean polling; - private @Nullable Boolean useClientPreference; - private List acceptedOutputModes = new ArrayList<>(); - private @Nullable PushNotificationConfig pushNotificationConfig; - private @Nullable Integer historyLength; - private Map metadata = new HashMap<>(); - - /** - * Enable or disable streaming mode. - *

- * When enabled, the client will use streaming communication if the agent also - * supports it. When disabled, the client uses blocking request-response mode. - * - * @param streaming {@code true} to enable streaming (default), {@code false} to disable - * @return this builder for method chaining - */ - public Builder setStreaming(@Nullable Boolean streaming) { - this.streaming = streaming; - return this; - } - - /** - * Enable or disable polling mode for task updates. - *

- * When enabled, the client can poll for task status instead of blocking or streaming. - * Useful for asynchronous workflows. - * - * @param polling {@code true} to enable polling, {@code false} otherwise (default) - * @return this builder for method chaining - */ - public Builder setPolling(@Nullable Boolean polling) { - this.polling = polling; - return this; - } - - /** - * Set whether to use client or server transport preference. - *

- * When {@code true}, the client's transport order (from {@link io.a2a.client.ClientBuilder#withTransport} - * calls) takes priority. When {@code false} (default), the server's preferred transport - * (first in {@link io.a2a.spec.AgentCard#supportedInterfaces()}) is used. - * - * @param useClientPreference {@code true} for client preference, {@code false} for server preference (default) - * @return this builder for method chaining - */ - public Builder setUseClientPreference(@Nullable Boolean useClientPreference) { - this.useClientPreference = useClientPreference; - return this; - } - - /** - * Set the accepted output modes. - *

- * Specify which content types the client can handle (e.g., "text", "audio", "image"). - * An empty list (default) means all modes are accepted. - *

- * The provided list is copied, so subsequent modifications won't affect this configuration. - * - * @param acceptedOutputModes the list of accepted output modes - * @return this builder for method chaining - */ - public Builder setAcceptedOutputModes(List acceptedOutputModes) { - this.acceptedOutputModes = new ArrayList<>(acceptedOutputModes); - return this; - } - - /** - * Set the default push notification configuration. - *

- * This webhook configuration will be used for all sendMessage calls - * unless overridden. The agent will POST task update events to the specified URL. - * - * @param pushNotificationConfig the push notification configuration - * @return this builder for method chaining - * @see io.a2a.client.Client#sendMessage(io.a2a.spec.Message, io.a2a.spec.PushNotificationConfig, java.util.Map, io.a2a.client.transport.spi.interceptors.ClientCallContext) - */ - public Builder setPushNotificationConfig(PushNotificationConfig pushNotificationConfig) { - this.pushNotificationConfig = pushNotificationConfig; - return this; - } - - /** - * Set the conversation history length. - *

- * Specify how many previous messages should be included as context when sending - * a new message. For example, 10 means the last 10 messages are sent to the agent - * for context. - * - * @param historyLength the number of previous messages to include (must be positive) - * @return this builder for method chaining - */ - public Builder setHistoryLength(Integer historyLength) { - this.historyLength = historyLength; - return this; - } - - /** - * Set custom metadata to be included in all requests. - *

- * This metadata is attached to every message sent by the client. Useful for - * tracking user IDs, session identifiers, client version, etc. - *

- * The provided map is copied, so subsequent modifications won't affect this configuration. - * - * @param metadata the custom metadata map - * @return this builder for method chaining - */ - public Builder setMetadata(Map metadata) { - this.metadata = metadata; - return this; - } - - /** - * Build the ClientConfig with the configured settings. - *

- * Any unset options will use their default values: - *

    - *
  • streaming: {@code true}
  • - *
  • polling: {@code false}
  • - *
  • useClientPreference: {@code false}
  • - *
  • acceptedOutputModes: empty list
  • - *
  • pushNotificationConfig: {@code null}
  • - *
  • historyLength: {@code null}
  • - *
  • metadata: empty map
  • - *
- * - * @return the configured ClientConfig instance - */ - public ClientConfig build() { - return new ClientConfig(this); - } - } -} \ No newline at end of file diff --git a/client/base/src/main/java/io/a2a/client/config/package-info.java b/client/base/src/main/java/io/a2a/client/config/package-info.java deleted file mode 100644 index ab8c28600..000000000 --- a/client/base/src/main/java/io/a2a/client/config/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.config; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/base/src/main/java/io/a2a/client/package-info.java b/client/base/src/main/java/io/a2a/client/package-info.java deleted file mode 100644 index 73cc3eef8..000000000 --- a/client/base/src/main/java/io/a2a/client/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/base/src/main/resources/META-INF/beans.xml b/client/base/src/main/resources/META-INF/beans.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/base/src/test/java/io/a2a/A2ATest.java b/client/base/src/test/java/io/a2a/A2ATest.java deleted file mode 100644 index 1052ad76d..000000000 --- a/client/base/src/test/java/io/a2a/A2ATest.java +++ /dev/null @@ -1,147 +0,0 @@ -package io.a2a; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; - -public class A2ATest { - - @Test - public void testToUserMessage() { - String text = "Hello, world!"; - Message message = A2A.toUserMessage(text); - - assertEquals(Message.Role.ROLE_USER, message.role()); - assertEquals(1, message.parts().size()); - assertEquals(text, ((TextPart) message.parts().get(0)).text()); - assertNotNull(message.messageId()); - assertNull(message.contextId()); - assertNull(message.taskId()); - } - - @Test - public void testToUserMessageWithId() { - String text = "Hello, world!"; - String messageId = "test-message-id"; - Message message = A2A.toUserMessage(text, messageId); - - assertEquals(Message.Role.ROLE_USER, message.role()); - assertEquals(messageId, message.messageId()); - } - - @Test - public void testToAgentMessage() { - String text = "Hello, I'm an agent!"; - Message message = A2A.toAgentMessage(text); - - assertEquals(Message.Role.ROLE_AGENT, message.role()); - assertEquals(1, message.parts().size()); - assertEquals(text, ((TextPart) message.parts().get(0)).text()); - assertNotNull(message.messageId()); - } - - @Test - public void testToAgentMessageWithId() { - String text = "Hello, I'm an agent!"; - String messageId = "agent-message-id"; - Message message = A2A.toAgentMessage(text, messageId); - - assertEquals(Message.Role.ROLE_AGENT, message.role()); - assertEquals(messageId, message.messageId()); - } - - @Test - public void testCreateUserTextMessage() { - String text = "User message with context"; - String contextId = "context-123"; - String taskId = "task-456"; - - Message message = A2A.createUserTextMessage(text, contextId, taskId); - - assertEquals(Message.Role.ROLE_USER, message.role()); - assertEquals(contextId, message.contextId()); - assertEquals(taskId, message.taskId()); - assertEquals(1, message.parts().size()); - assertEquals(text, ((TextPart) message.parts().get(0)).text()); - assertNotNull(message.messageId()); - assertNull(message.metadata()); - assertNull(message.referenceTaskIds()); - } - - @Test - public void testCreateUserTextMessageWithNullParams() { - String text = "Simple user message"; - - Message message = A2A.createUserTextMessage(text, null, null); - - assertEquals(Message.Role.ROLE_USER, message.role()); - assertNull(message.contextId()); - assertNull(message.taskId()); - assertEquals(1, message.parts().size()); - assertEquals(text, ((TextPart) message.parts().get(0)).text()); - } - - @Test - public void testCreateAgentTextMessage() { - String text = "Agent message with context"; - String contextId = "context-789"; - String taskId = "task-012"; - - Message message = A2A.createAgentTextMessage(text, contextId, taskId); - - assertEquals(Message.Role.ROLE_AGENT, message.role()); - assertEquals(contextId, message.contextId()); - assertEquals(taskId, message.taskId()); - assertEquals(1, message.parts().size()); - assertEquals(text, ((TextPart) message.parts().get(0)).text()); - assertNotNull(message.messageId()); - } - - @Test - public void testCreateAgentPartsMessage() { - List> parts = Arrays.asList( - new TextPart("Part 1"), - new TextPart("Part 2") - ); - String contextId = "context-parts"; - String taskId = "task-parts"; - - Message message = A2A.createAgentPartsMessage(parts, contextId, taskId); - - assertEquals(Message.Role.ROLE_AGENT, message.role()); - assertEquals(contextId, message.contextId()); - assertEquals(taskId, message.taskId()); - assertEquals(2, message.parts().size()); - assertEquals("Part 1", ((TextPart) message.parts().get(0)).text()); - assertEquals("Part 2", ((TextPart) message.parts().get(1)).text()); - } - - @Test - public void testCreateAgentPartsMessageWithNullParts() { - try { - A2A.createAgentPartsMessage(null, "context", "task"); - org.junit.jupiter.api.Assertions.fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - assertEquals("Parts cannot be null or empty", e.getMessage()); - } - } - - @Test - public void testCreateAgentPartsMessageWithEmptyParts() { - try { - A2A.createAgentPartsMessage(Collections.emptyList(), "context", "task"); - org.junit.jupiter.api.Assertions.fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - assertEquals("Parts cannot be null or empty", e.getMessage()); - } - } -} \ No newline at end of file diff --git a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java b/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java deleted file mode 100644 index 5d0e9b8e9..000000000 --- a/client/base/src/test/java/io/a2a/client/AuthenticationAuthorizationTest.java +++ /dev/null @@ -1,378 +0,0 @@ -package io.a2a.client; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import java.io.IOException; -import java.util.Collections; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; -import io.a2a.grpc.A2AServiceGrpc; -import io.a2a.grpc.SendMessageRequest; -import io.a2a.grpc.SendMessageResponse; -import io.a2a.grpc.StreamResponse; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.Message; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; -import io.grpc.ManagedChannel; -import io.grpc.Server; -import io.grpc.Status; -import io.grpc.inprocess.InProcessChannelBuilder; -import io.grpc.inprocess.InProcessServerBuilder; -import io.grpc.stub.StreamObserver; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; - -/** - * Tests for handling HTTP 401 (Unauthorized) and 403 (Forbidden) responses - * when the client sends streaming and non-streaming messages. - * - * These tests verify that the client properly fails when the server returns - * authentication or authorization errors. - */ -public class AuthenticationAuthorizationTest { - - private static final String AGENT_URL = "http://localhost:4001"; - private static final String AUTHENTICATION_FAILED_MESSAGE = "Authentication failed"; - private static final String AUTHORIZATION_FAILED_MESSAGE = "Authorization failed"; - - private ClientAndServer server; - private Message MESSAGE; - private AgentCard agentCard; - private Server grpcServer; - private ManagedChannel grpcChannel; - private String grpcServerName; - - @BeforeEach - public void setUp() { - server = new ClientAndServer(4001); - MESSAGE = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("test message"))) - .contextId("context-1234") - .messageId("message-1234") - .build(); - - grpcServerName = InProcessServerBuilder.generateName(); - - agentCard = AgentCard.builder() - .name("Test Agent") - .description("Test agent for auth tests") - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) // Support streaming for all tests - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(AgentSkill.builder() - .id("test_skill") - .name("Test skill") - .description("Test skill") - .tags(Collections.singletonList("test")) - .build())) - .supportedInterfaces(java.util.Arrays.asList( - new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL), - new AgentInterface(TransportProtocol.HTTP_JSON.asString(), AGENT_URL), - new AgentInterface(TransportProtocol.GRPC.asString(), grpcServerName))) - .build(); - } - - @AfterEach - public void tearDown() { - server.stop(); - if (grpcChannel != null) { - grpcChannel.shutdownNow(); - } - if (grpcServer != null) { - grpcServer.shutdownNow(); - } - } - - // ========== JSON-RPC Transport Tests ========== - - @Test - public void testJsonRpcNonStreamingUnauthenticated() throws A2AClientException { - // Mock server to return 401 for non-streaming message - server.when( - request() - .withMethod("POST") - .withPath("/") - ).respond( - response() - .withStatusCode(401) - ); - - Client client = getJSONRPCClientBuilder(false).build(); - - A2AClientException exception = assertThrows(A2AClientException.class, () -> { - client.sendMessage(MESSAGE); - }); - - assertTrue(exception.getMessage().contains(AUTHENTICATION_FAILED_MESSAGE)); - } - - @Test - public void testJsonRpcNonStreamingUnauthorized() throws A2AClientException { - // Mock server to return 403 for non-streaming message - server.when( - request() - .withMethod("POST") - .withPath("/") - ).respond( - response() - .withStatusCode(403) - ); - - Client client = getJSONRPCClientBuilder(false).build(); - - A2AClientException exception = assertThrows(A2AClientException.class, () -> { - client.sendMessage(MESSAGE); - }); - - assertTrue(exception.getMessage().contains(AUTHORIZATION_FAILED_MESSAGE)); - } - - @Test - public void testJsonRpcStreamingUnauthenticated() throws Exception { - // Mock server to return 401 for streaming message - server.when( - request() - .withMethod("POST") - .withPath("/") - ).respond( - response() - .withStatusCode(401) - ); - - assertStreamingError( - getJSONRPCClientBuilder(true), - AUTHENTICATION_FAILED_MESSAGE); - } - - @Test - public void testJsonRpcStreamingUnauthorized() throws Exception { - // Mock server to return 403 for streaming message - server.when( - request() - .withMethod("POST") - .withPath("/") - ).respond( - response() - .withStatusCode(403) - ); - - assertStreamingError( - getJSONRPCClientBuilder(true), - AUTHORIZATION_FAILED_MESSAGE); - } - - // ========== REST Transport Tests ========== - - @Test - public void testRestNonStreamingUnauthenticated() throws A2AClientException { - // Mock server to return 401 for non-streaming message - server.when( - request() - .withMethod("POST") - .withPath("/message:send") - ).respond( - response() - .withStatusCode(401) - ); - - Client client = getRestClientBuilder(false).build(); - - A2AClientException exception = assertThrows(A2AClientException.class, () -> { - client.sendMessage(MESSAGE); - }); - - assertTrue(exception.getMessage().contains(AUTHENTICATION_FAILED_MESSAGE)); - } - - @Test - public void testRestNonStreamingUnauthorized() throws A2AClientException { - // Mock server to return 403 for non-streaming message - server.when( - request() - .withMethod("POST") - .withPath("/message:send") - ).respond( - response() - .withStatusCode(403) - ); - - Client client = getRestClientBuilder(false).build(); - - A2AClientException exception = assertThrows(A2AClientException.class, () -> { - client.sendMessage(MESSAGE); - }); - - assertTrue(exception.getMessage().contains(AUTHORIZATION_FAILED_MESSAGE)); - } - - @Test - public void testRestStreamingUnauthenticated() throws Exception { - // Mock server to return 401 for streaming message - server.when( - request() - .withMethod("POST") - .withPath("/message:stream") - ).respond( - response() - .withStatusCode(401) - ); - - assertStreamingError( - getRestClientBuilder(true), - AUTHENTICATION_FAILED_MESSAGE); - } - - @Test - public void testRestStreamingUnauthorized() throws Exception { - // Mock server to return 403 for streaming message - server.when( - request() - .withMethod("POST") - .withPath("/message:stream") - ).respond( - response() - .withStatusCode(403) - ); - - assertStreamingError( - getRestClientBuilder(true), - AUTHORIZATION_FAILED_MESSAGE); - } - - // ========== gRPC Transport Tests ========== - - @Test - public void testGrpcNonStreamingUnauthenticated() throws Exception { - setupGrpcServer(Status.UNAUTHENTICATED); - - Client client = getGrpcClientBuilder(false).build(); - - A2AClientException exception = assertThrows(A2AClientException.class, () -> { - client.sendMessage(MESSAGE); - }); - - assertTrue(exception.getMessage().contains(AUTHENTICATION_FAILED_MESSAGE)); - } - - @Test - public void testGrpcNonStreamingUnauthorized() throws Exception { - setupGrpcServer(Status.PERMISSION_DENIED); - - Client client = getGrpcClientBuilder(false).build(); - - A2AClientException exception = assertThrows(A2AClientException.class, () -> { - client.sendMessage(MESSAGE); - }); - - assertTrue(exception.getMessage().contains(AUTHORIZATION_FAILED_MESSAGE)); - } - - @Test - public void testGrpcStreamingUnauthenticated() throws Exception { - setupGrpcServer(Status.UNAUTHENTICATED); - - assertStreamingError( - getGrpcClientBuilder(true), - AUTHENTICATION_FAILED_MESSAGE); - } - - @Test - public void testGrpcStreamingUnauthorized() throws Exception { - setupGrpcServer(Status.PERMISSION_DENIED); - - assertStreamingError( - getGrpcClientBuilder(true), - AUTHORIZATION_FAILED_MESSAGE); - } - - private ClientBuilder getJSONRPCClientBuilder(boolean streaming) { - return Client.builder(agentCard) - .clientConfig(new ClientConfig.Builder().setStreaming(streaming).build()) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()); - } - - private ClientBuilder getRestClientBuilder(boolean streaming) { - return Client.builder(agentCard) - .clientConfig(new ClientConfig.Builder().setStreaming(streaming).build()) - .withTransport(RestTransport.class, new RestTransportConfigBuilder()); - } - - private ClientBuilder getGrpcClientBuilder(boolean streaming) { - return Client.builder(agentCard) - .clientConfig(new ClientConfig.Builder().setStreaming(streaming).build()) - .withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder() - .channelFactory(target -> grpcChannel)); - } - - private void assertStreamingError(ClientBuilder clientBuilder, String expectedErrorMessage) throws Exception { - AtomicReference errorRef = new AtomicReference<>(); - CountDownLatch errorLatch = new CountDownLatch(1); - - Consumer errorHandler = error -> { - errorRef.set(error); - errorLatch.countDown(); - }; - - Client client = clientBuilder.streamingErrorHandler(errorHandler).build(); - - try { - client.sendMessage(MESSAGE); - // If no immediate exception, wait for async error - assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); - Throwable error = errorRef.get(); - assertTrue(error.getMessage().contains(expectedErrorMessage), - "Expected error message to contain '" + expectedErrorMessage + "' but got: " + error.getMessage()); - } catch (Exception e) { - // Immediate exception is also acceptable - assertTrue(e.getMessage().contains(expectedErrorMessage), - "Expected error message to contain '" + expectedErrorMessage + "' but got: " + e.getMessage()); - } - } - - private void setupGrpcServer(Status status) throws IOException { - grpcServerName = InProcessServerBuilder.generateName(); - grpcServer = InProcessServerBuilder.forName(grpcServerName) - .directExecutor() - .addService(new A2AServiceGrpc.A2AServiceImplBase() { - @Override - public void sendMessage(SendMessageRequest request, StreamObserver responseObserver) { - responseObserver.onError(status.asRuntimeException()); - } - - @Override - public void sendStreamingMessage(SendMessageRequest request, StreamObserver responseObserver) { - responseObserver.onError(status.asRuntimeException()); - } - }) - .build() - .start(); - - grpcChannel = InProcessChannelBuilder.forName(grpcServerName) - .directExecutor() - .build(); - } -} \ No newline at end of file diff --git a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java b/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java deleted file mode 100644 index 3be9d4918..000000000 --- a/client/base/src/test/java/io/a2a/client/ClientBuilderTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package io.a2a.client; - - -import java.util.Collections; -import java.util.List; - -import io.a2a.client.config.ClientConfig; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class ClientBuilderTest { - - private AgentCard card = AgentCard.builder() - .name("Hello World Agent") - .description("Just a hello world agent") - .version("1.0.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(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())) - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) - .build(); - - @Test - public void shouldNotFindCompatibleTransport() throws A2AClientException { - A2AClientException exception = Assertions.assertThrows(A2AClientException.class, - () -> Client - .builder(card) - .clientConfig(new ClientConfig.Builder().setUseClientPreference(true).build()) - .withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder() - .channelFactory(s -> null)) - .build()); - - Assertions.assertTrue(exception.getMessage() != null && exception.getMessage().contains("No compatible transport found")); - } - - @Test - public void shouldNotFindConfigurationTransport() throws A2AClientException { - A2AClientException exception = Assertions.assertThrows(A2AClientException.class, - () -> Client - .builder(card) - .clientConfig(new ClientConfig.Builder().setUseClientPreference(true).build()) - .build()); - - Assertions.assertTrue(exception.getMessage() != null && exception.getMessage().startsWith("Missing required TransportConfig for")); - } - - @Test - public void shouldCreateJSONRPCClient() throws A2AClientException { - Client client = Client - .builder(card) - .clientConfig(new ClientConfig.Builder().setUseClientPreference(true).build()) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder() - .addInterceptor(null) - .httpClient(null)) - .build(); - - Assertions.assertNotNull(client); - } - - @Test - public void shouldCreateClient_differentConfigurations() throws A2AClientException { - Client client = Client - .builder(card) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig(A2AHttpClientFactory.create())) - .build(); - - Assertions.assertNotNull(client); - } -} diff --git a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java b/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java deleted file mode 100644 index 74699b97e..000000000 --- a/client/base/src/test/java/io/a2a/client/ClientTaskManagerTest.java +++ /dev/null @@ -1,323 +0,0 @@ -package io.a2a.client; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.spec.A2AClientInvalidArgsError; -import io.a2a.spec.A2AClientInvalidStateError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class ClientTaskManagerTest { - - private ClientTaskManager taskManager; - private Task sampleTask; - private Message sampleMessage; - - @BeforeEach - public void setUp() { - taskManager = new ClientTaskManager(); - - sampleTask = Task.builder() - .id("task123") - .contextId("context456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - sampleMessage = Message.builder() - .messageId("msg1") - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("Hello"))) - .build(); - } - - @Test - public void testGetCurrentTaskNoTaskRaisesError() { - A2AClientInvalidStateError exception = assertThrows( - A2AClientInvalidStateError.class, - () -> taskManager.getCurrentTask() - ); - assertTrue(exception.getMessage().contains("No current task")); - } - - @Test - public void testSaveTaskEventWithTask() throws Exception { - Task result = taskManager.saveTaskEvent(sampleTask); - - assertEquals(sampleTask, taskManager.getCurrentTask()); - assertEquals(sampleTask, result); - } - - @Test - public void testSaveTaskEventWithTaskAlreadySetRaisesError() throws Exception { - taskManager.saveTaskEvent(sampleTask); - - A2AClientInvalidArgsError exception = assertThrows( - A2AClientInvalidArgsError.class, - () -> taskManager.saveTaskEvent(sampleTask) - ); - assertTrue(exception.getMessage().contains("Task is already set, create new manager for new tasks.")); - } - - @Test - public void testSaveTaskEventWithStatusUpdate() throws Exception { - taskManager.saveTaskEvent(sampleTask); - - TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() - .taskId(sampleTask.id()) - .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED, sampleMessage, null)) - .build(); - - Task updatedTask = taskManager.saveTaskEvent(statusUpdate); - - assertEquals(TaskState.TASK_STATE_COMPLETED, updatedTask.status().state()); - assertNotNull(updatedTask.history()); - assertEquals(1, updatedTask.history().size()); - assertEquals(sampleMessage, updatedTask.history().get(0)); - } - - @Test - public void testSaveTaskEventWithStatusUpdateAndMetadata() throws Exception { - taskManager.saveTaskEvent(sampleTask); - - Map metadata = new HashMap<>(); - metadata.put("key1", "value1"); - metadata.put("key2", 42); - - TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() - .taskId(sampleTask.id()) - .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .metadata(metadata) - .build(); - - Task updatedTask = taskManager.saveTaskEvent(statusUpdate); - - assertNotNull(updatedTask.metadata()); - assertEquals("value1", updatedTask.metadata().get("key1")); - assertEquals(42, updatedTask.metadata().get("key2")); - } - - @Test - public void testSaveTaskEventWithArtifactUpdate() throws Exception { - taskManager.saveTaskEvent(sampleTask); - - Artifact artifact = Artifact.builder() - .artifactId("art1") - .parts(Collections.singletonList(new TextPart("artifact content"))) - .build(); - - TaskArtifactUpdateEvent artifactUpdate = TaskArtifactUpdateEvent.builder() - .taskId(sampleTask.id()) - .contextId(sampleTask.contextId()) - .artifact(artifact) - .build(); - - Task updatedTask = taskManager.saveTaskEvent(artifactUpdate); - - assertNotNull(updatedTask); - assertNotNull(updatedTask.artifacts()); - assertEquals(1, updatedTask.artifacts().size()); - assertEquals("art1", updatedTask.artifacts().get(0).artifactId()); - } - - @Test - public void testSaveTaskEventCreatesTaskIfNotExists() throws Exception { - TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() - .taskId("new_task") - .contextId("new_context") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - Task updatedTask = taskManager.saveTaskEvent(statusUpdate); - - assertNotNull(updatedTask); - assertEquals("new_task", updatedTask.id()); - assertEquals("new_context", updatedTask.contextId()); - assertEquals(TaskState.TASK_STATE_WORKING, updatedTask.status().state()); - } - - @Test - public void testSaveTaskEventCreatesTaskFromArtifactUpdateIfNotExists() { - Artifact artifact = Artifact.builder() - .artifactId("art1") - .parts(Collections.singletonList(new TextPart("artifact content"))) - .build(); - - TaskArtifactUpdateEvent artifactUpdate = TaskArtifactUpdateEvent.builder() - .taskId("new_task_id") - .contextId("new_context_id") - .artifact(artifact) - .build(); - - Task updatedTask = taskManager.saveTaskEvent(artifactUpdate); - - assertNotNull(updatedTask); - assertEquals("new_task_id", updatedTask.id()); - assertEquals("new_context_id", updatedTask.contextId()); - assertNotNull(updatedTask.artifacts()); - assertEquals(1, updatedTask.artifacts().size()); - } - - @Test - public void testUpdateWithMessage() { - // Use a task with mutable history list initialized properly - Task taskWithHistory = Task.builder() - .id("task123") - .contextId("context456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithHistory); - - assertNotNull(updatedTask.history()); - assertEquals(1, updatedTask.history().size()); - assertEquals(sampleMessage, updatedTask.history().get(0)); - } - - @Test - public void testUpdateWithMessageMovesStatusMessage() { - Message statusMessage = Message.builder() - .messageId("status_msg") - .role(Message.Role.ROLE_AGENT) - .parts(Collections.singletonList(new TextPart("Status"))) - .build(); - - Task taskWithStatusMessage = Task.builder() - .id("task123") - .contextId("context456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, statusMessage, null)) - .build(); - - Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithStatusMessage); - - assertNotNull(updatedTask.history()); - assertEquals(2, updatedTask.history().size()); - assertEquals(statusMessage, updatedTask.history().get(0)); - assertEquals(sampleMessage, updatedTask.history().get(1)); - assertNull(updatedTask.status().message()); - } - - @Test - public void testUpdateWithMessagePreservesExistingHistory() { - Message existingMessage = Message.builder() - .messageId("existing_msg") - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("Existing"))) - .build(); - - Task taskWithHistory = Task.builder() - .id("task123") - .contextId("context456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .history(List.of(existingMessage)) - .build(); - - Task updatedTask = taskManager.updateWithMessage(sampleMessage, taskWithHistory); - - assertNotNull(updatedTask.history()); - assertEquals(2, updatedTask.history().size()); - assertEquals(existingMessage, updatedTask.history().get(0)); - assertEquals(sampleMessage, updatedTask.history().get(1)); - } - - @Test - public void testSaveTaskEventMultipleStatusUpdates() throws Exception { - taskManager.saveTaskEvent(sampleTask); - - // First status update - TaskStatusUpdateEvent statusUpdate1 = TaskStatusUpdateEvent.builder() - .taskId(sampleTask.id()) - .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, sampleMessage, null)) - .build(); - - Task updatedTask1 = taskManager.saveTaskEvent(statusUpdate1); - assertEquals(TaskState.TASK_STATE_WORKING, updatedTask1.status().state()); - assertEquals(1, updatedTask1.history().size()); - - // Second status update - Message secondMessage = Message.builder() - .messageId("msg2") - .role(Message.Role.ROLE_AGENT) - .parts(Collections.singletonList(new TextPart("Second message"))) - .build(); - - TaskStatusUpdateEvent statusUpdate2 = TaskStatusUpdateEvent.builder() - .taskId(sampleTask.id()) - .contextId(sampleTask.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED, secondMessage, null)) - .build(); - - Task updatedTask2 = taskManager.saveTaskEvent(statusUpdate2); - assertEquals(TaskState.TASK_STATE_COMPLETED, updatedTask2.status().state()); - assertEquals(2, updatedTask2.history().size()); - } - - @Test - public void testSaveTaskEventMultipleArtifactUpdates() throws Exception { - taskManager.saveTaskEvent(sampleTask); - - // First artifact update - Artifact artifact1 = Artifact.builder() - .artifactId("art1") - .parts(Collections.singletonList(new TextPart("First artifact"))) - .build(); - - TaskArtifactUpdateEvent artifactUpdate1 = TaskArtifactUpdateEvent.builder() - .taskId(sampleTask.id()) - .contextId(sampleTask.contextId()) - .artifact(artifact1) - .build(); - - Task updatedTask1 = taskManager.saveTaskEvent(artifactUpdate1); - assertEquals(1, updatedTask1.artifacts().size()); - - // Second artifact update - Artifact artifact2 = Artifact.builder() - .artifactId("art2") - .parts(Collections.singletonList(new TextPart("Second artifact"))) - .build(); - - TaskArtifactUpdateEvent artifactUpdate2 = TaskArtifactUpdateEvent.builder() - .taskId(sampleTask.id()) - .contextId(sampleTask.contextId()) - .artifact(artifact2) - .build(); - - Task updatedTask2 = taskManager.saveTaskEvent(artifactUpdate2); - assertEquals(2, updatedTask2.artifacts().size()); - } - - @Test - public void testSaveTaskEventWithEmptyContextId() throws Exception { - TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() - .taskId("task_with_empty_context") - .contextId("") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - Task updatedTask = taskManager.saveTaskEvent(statusUpdate); - - assertNotNull(updatedTask); - assertEquals("task_with_empty_context", updatedTask.id()); - assertEquals("", updatedTask.contextId()); - } -} diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml deleted file mode 100644 index 8ca49f274..000000000 --- a/client/transport/grpc/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../../pom.xml - - a2a-java-sdk-client-transport-grpc - jar - - Java SDK A2A Client Transport: gRPC - Java SDK for the Agent2Agent Protocol (A2A) - gRPC Client Transport - - - - ${project.groupId} - a2a-java-sdk-common - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-spec-grpc - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - - - io.grpc - grpc-protobuf - - - io.grpc - grpc-stub - - - org.junit.jupiter - junit-jupiter-api - test - - - - org.mock-server - mockserver-netty - test - - - - \ No newline at end of file diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java deleted file mode 100644 index 0c928bd75..000000000 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.a2a.client.transport.grpc; - - -import static io.a2a.grpc.utils.ProtoUtils.FromProto; - -import java.util.function.Consumer; -import java.util.logging.Logger; - -import io.a2a.grpc.StreamResponse; -import io.a2a.spec.StreamingEventKind; -import io.grpc.stub.StreamObserver; - -public class EventStreamObserver implements StreamObserver { - - private static final Logger log = Logger.getLogger(EventStreamObserver.class.getName()); - private final Consumer eventHandler; - private final Consumer errorHandler; - - public EventStreamObserver(Consumer eventHandler, Consumer errorHandler) { - this.eventHandler = eventHandler; - this.errorHandler = errorHandler; - } - - @Override - public void onNext(StreamResponse response) { - StreamingEventKind event; - switch (response.getPayloadCase()) { - case MESSAGE: - event = FromProto.message(response.getMessage()); - break; - case TASK: - event = FromProto.task(response.getTask()); - break; - case STATUS_UPDATE: - event = FromProto.taskStatusUpdateEvent(response.getStatusUpdate()); - break; - case ARTIFACT_UPDATE: - event = FromProto.taskArtifactUpdateEvent(response.getArtifactUpdate()); - break; - default: - log.warning("Invalid stream response " + response.getPayloadCase()); - errorHandler.accept(new IllegalStateException("Invalid stream response from server: " + response.getPayloadCase())); - return; - } - eventHandler.accept(event); - } - - @Override - public void onError(Throwable t) { - if (errorHandler != null) { - // Map gRPC errors to proper A2A exceptions - if (t instanceof io.grpc.StatusRuntimeException) { - errorHandler.accept(GrpcErrorMapper.mapGrpcError((io.grpc.StatusRuntimeException) t)); - } else { - errorHandler.accept(t); - } - } - } - - @Override - public void onCompleted() { - // done - } -} diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java deleted file mode 100644 index b9ad3325b..000000000 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcErrorMapper.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.a2a.client.transport.grpc; - -import io.a2a.common.A2AErrorMessages; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; -import io.grpc.Status; - -/** - * Utility class to map gRPC exceptions to appropriate A2A error types - */ -public class GrpcErrorMapper { - - public static A2AClientException mapGrpcError(Throwable e) { - return mapGrpcError(e, "gRPC error: "); - } - - public static A2AClientException mapGrpcError(Throwable e, String errorPrefix) { - Status status = Status.fromThrowable(e); - Status.Code code = status.getCode(); - String description = status.getDescription(); - - // Extract the actual error type from the description if possible - // (using description because the same code can map to multiple errors - - // see GrpcHandler#handleError) - if (description != null) { - if (description.contains("TaskNotFoundError")) { - return new A2AClientException(errorPrefix + description, new TaskNotFoundError()); - } else if (description.contains("UnsupportedOperationError")) { - return new A2AClientException(errorPrefix + description, new UnsupportedOperationError()); - } else if (description.contains("InvalidParamsError")) { - return new A2AClientException(errorPrefix + description, new InvalidParamsError()); - } else if (description.contains("InvalidRequestError")) { - return new A2AClientException(errorPrefix + description, new InvalidRequestError()); - } else if (description.contains("MethodNotFoundError")) { - return new A2AClientException(errorPrefix + description, new MethodNotFoundError()); - } else if (description.contains("TaskNotCancelableError")) { - return new A2AClientException(errorPrefix + description, new TaskNotCancelableError()); - } else if (description.contains("PushNotificationNotSupportedError")) { - return new A2AClientException(errorPrefix + description, new PushNotificationNotSupportedError()); - } else if (description.contains("JSONParseError")) { - return new A2AClientException(errorPrefix + description, new JSONParseError()); - } else if (description.contains("ContentTypeNotSupportedError")) { - return new A2AClientException(errorPrefix + description, new ContentTypeNotSupportedError(null, description, null)); - } else if (description.contains("InvalidAgentResponseError")) { - return new A2AClientException(errorPrefix + description, new InvalidAgentResponseError(null, description, null)); - } else if (description.contains("ExtendedCardNotConfiguredError")) { - return new A2AClientException(errorPrefix + description, new ExtendedAgentCardNotConfiguredError(null, description, null)); - } else if (description.contains("ExtensionSupportRequiredError")) { - return new A2AClientException(errorPrefix + description, new ExtensionSupportRequiredError(null, description, null)); - } else if (description.contains("VersionNotSupportedError")) { - return new A2AClientException(errorPrefix + description, new VersionNotSupportedError(null, description, null)); - } - } - - // Fall back to mapping based on status code - switch (code) { - case NOT_FOUND: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new TaskNotFoundError()); - case UNIMPLEMENTED: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new UnsupportedOperationError()); - case INVALID_ARGUMENT: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new InvalidParamsError()); - case INTERNAL: - return new A2AClientException(errorPrefix + (description != null ? description : e.getMessage()), new io.a2a.spec.InternalError(null, e.getMessage(), null)); - case UNAUTHENTICATED: - return new A2AClientException(errorPrefix + A2AErrorMessages.AUTHENTICATION_FAILED); - case PERMISSION_DENIED: - return new A2AClientException(errorPrefix + A2AErrorMessages.AUTHORIZATION_FAILED); - default: - return new A2AClientException(errorPrefix + e.getMessage(), e); - } - } -} diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java deleted file mode 100644 index ca849d99c..000000000 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java +++ /dev/null @@ -1,469 +0,0 @@ -package io.a2a.client.transport.grpc; - -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; -import static io.a2a.util.Assert.checkNotNullParam; - -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; -import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; -import io.a2a.client.transport.spi.interceptors.auth.AuthInterceptor; -import io.a2a.common.A2AHeaders; -import io.a2a.grpc.A2AServiceGrpc; -import io.a2a.grpc.A2AServiceGrpc.A2AServiceBlockingV2Stub; -import io.a2a.grpc.A2AServiceGrpc.A2AServiceStub; -import io.a2a.grpc.GetExtendedAgentCardRequest; -import io.a2a.grpc.utils.ProtoUtils.FromProto; -import io.a2a.grpc.utils.ProtoUtils.ToProto; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.grpc.Channel; -import io.grpc.Metadata; -import io.grpc.StatusException; -import io.grpc.StatusRuntimeException; -import io.grpc.stub.MetadataUtils; -import io.grpc.stub.StreamObserver; -import org.jspecify.annotations.Nullable; - -public class GrpcTransport implements ClientTransport { - - private static final Metadata.Key AUTHORIZATION_METADATA_KEY = Metadata.Key.of( - AuthInterceptor.AUTHORIZATION, - Metadata.ASCII_STRING_MARSHALLER); - private static final Metadata.Key EXTENSIONS_KEY = Metadata.Key.of( - A2AHeaders.X_A2A_EXTENSIONS, - Metadata.ASCII_STRING_MARSHALLER); - private static final Metadata.Key VERSION_KEY = Metadata.Key.of( - A2AHeaders.X_A2A_VERSION, - Metadata.ASCII_STRING_MARSHALLER); - private final A2AServiceBlockingV2Stub blockingStub; - private final A2AServiceStub asyncStub; - private final @Nullable List interceptors; - private final AgentCard agentCard; - private final String agentTenant; - - public GrpcTransport(Channel channel, AgentCard agentCard) { - this(channel, agentCard, "", null); - } - - public GrpcTransport(Channel channel, AgentCard agentCard, @Nullable String agentTenant, @Nullable List interceptors) { - checkNotNullParam("channel", channel); - checkNotNullParam("agentCard", agentCard); - this.asyncStub = A2AServiceGrpc.newStub(channel); - this.blockingStub = A2AServiceGrpc.newBlockingV2Stub(channel); - this.agentCard = agentCard; - this.interceptors = interceptors; - this.agentTenant = agentTenant == null || agentTenant.isBlank() ? "" : agentTenant; - } - - /** - * Resolves the tenant to use, preferring the request tenant over the agent default. - * - * @param requestTenant the tenant from the request, may be null or blank - * @return the tenant to use (request tenant if provided, otherwise agent default) - */ - private String resolveTenant(@Nullable String requestTenant) { - return (requestTenant == null || requestTenant.isBlank()) ? agentTenant : requestTenant; - } - - @Override - public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - MessageSendParams tenantRequest = createRequestWithTenant(request); - - io.a2a.grpc.SendMessageRequest sendMessageRequest = createGrpcSendMessageRequest(tenantRequest, context); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_MESSAGE_METHOD, sendMessageRequest, - agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - io.a2a.grpc.SendMessageResponse response = stubWithMetadata.sendMessage(sendMessageRequest); - if (response.hasMessage()) { - return FromProto.message(response.getMessage()); - } else if (response.hasTask()) { - return FromProto.task(response.getTask()); - } else { - throw new A2AClientException("Server response did not contain a message or task"); - } - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to send message: "); - } - } - - @Override - public void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - checkNotNullParam("eventConsumer", eventConsumer); - MessageSendParams tenantRequest = createRequestWithTenant(request); - - io.a2a.grpc.SendMessageRequest grpcRequest = createGrpcSendMessageRequest(tenantRequest, context); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_STREAMING_MESSAGE_METHOD, - grpcRequest, agentCard, context); - StreamObserver streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); - - try { - A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders); - stubWithMetadata.sendStreamingMessage(grpcRequest, streamObserver); - } catch (StatusRuntimeException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to send streaming message request: "); - } - } - - @Override - public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - io.a2a.grpc.GetTaskRequest.Builder requestBuilder = io.a2a.grpc.GetTaskRequest.newBuilder(); - requestBuilder.setId(request.id()); - if (request.historyLength() != null) { - requestBuilder.setHistoryLength(request.historyLength()); - } - requestBuilder.setTenant(resolveTenant(request.tenant())); - io.a2a.grpc.GetTaskRequest getTaskRequest = requestBuilder.build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_METHOD, getTaskRequest, - agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - return FromProto.task(stubWithMetadata.getTask(getTaskRequest)); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to get task: "); - } - } - - @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - - io.a2a.grpc.CancelTaskRequest cancelTaskRequest = io.a2a.grpc.CancelTaskRequest.newBuilder() - .setId(request.id()) - .setTenant(resolveTenant(request.tenant())) - .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(CANCEL_TASK_METHOD, cancelTaskRequest, agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - return FromProto.task(stubWithMetadata.cancelTask(cancelTaskRequest)); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to cancel task: "); - } - } - - @Override - public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - - io.a2a.grpc.ListTasksRequest.Builder requestBuilder = io.a2a.grpc.ListTasksRequest.newBuilder(); - if (request.contextId() != null) { - requestBuilder.setContextId(request.contextId()); - } - if (request.status() != null) { - requestBuilder.setStatus(ToProto.taskState(request.status())); - } - if (request.pageSize() != null) { - requestBuilder.setPageSize(request.pageSize()); - } - if (request.pageToken() != null) { - requestBuilder.setPageToken(request.pageToken()); - } - if (request.historyLength() != null) { - requestBuilder.setHistoryLength(request.historyLength()); - } - if (request.statusTimestampAfter() != null) { - requestBuilder.setStatusTimestampAfter( - com.google.protobuf.Timestamp.newBuilder() - .setSeconds(request.statusTimestampAfter().getEpochSecond()) - .setNanos(request.statusTimestampAfter().getNano()) - .build()); - } - if (request.includeArtifacts() != null) { - requestBuilder.setIncludeArtifacts(request.includeArtifacts()); - } - requestBuilder.setTenant(resolveTenant(request.tenant())); - io.a2a.grpc.ListTasksRequest listTasksRequest = requestBuilder.build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_METHOD, listTasksRequest, agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - io.a2a.grpc.ListTasksResponse grpcResponse = stubWithMetadata.listTasks(listTasksRequest); - - return new ListTasksResult( - grpcResponse.getTasksList().stream() - .map(FromProto::task) - .collect(Collectors.toList()), - grpcResponse.getTotalSize(), - grpcResponse.getTasksCount(), - grpcResponse.getNextPageToken().isEmpty() ? null : grpcResponse.getNextPageToken() - ); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to list tasks: "); - } - } - - @Override - public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - - String configId = request.config().id(); - io.a2a.grpc.CreateTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(request.taskId()) - .setConfig(ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) - .setConfigId(configId != null ? configId : request.taskId()) - .setTenant(resolveTenant(request.tenant())) - .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - return FromProto.taskPushNotificationConfig(stubWithMetadata.createTaskPushNotificationConfig(grpcRequest)); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to create task push notification config: "); - } - } - - @Override - public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - checkNotNullParam("taskId", request.taskId()); - if(request.id() == null) { - throw new IllegalArgumentException("Id must not be null"); - } - - io.a2a.grpc.GetTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(request.taskId()) - .setTenant(resolveTenant(request.tenant())) - .setId(request.id()) - .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - return FromProto.taskPushNotificationConfig(stubWithMetadata.getTaskPushNotificationConfig(grpcRequest)); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to get task push notification config: "); - } - } - - @Override - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - - io.a2a.grpc.ListTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(request.id()) - .setTenant(resolveTenant(request.tenant())) - .setPageSize(request.pageSize()) - .setPageToken(request.pageToken()) - .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - grpcRequest, agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - io.a2a.grpc.ListTaskPushNotificationConfigResponse grpcResponse = stubWithMetadata.listTaskPushNotificationConfig(grpcRequest); - return FromProto.listTaskPushNotificationConfigResult(grpcResponse); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to list task push notification config: "); - } - } - - @Override - public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest grpcRequest = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(request.taskId()) - .setId(request.id()) - .setTenant(resolveTenant(request.tenant())) - .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - stubWithMetadata.deleteTaskPushNotificationConfig(grpcRequest); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to delete task push notification config: "); - } - } - - @Override - public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - checkNotNullParam("eventConsumer", eventConsumer); - - io.a2a.grpc.SubscribeToTaskRequest grpcRequest = io.a2a.grpc.SubscribeToTaskRequest.newBuilder() - .setTenant(resolveTenant(request.tenant())) - .setId(request.id()) - .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, grpcRequest, agentCard, context); - - StreamObserver streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); - - try { - A2AServiceStub stubWithMetadata = createAsyncStubWithMetadata(context, payloadAndHeaders); - stubWithMetadata.subscribeToTask(grpcRequest, streamObserver); - } catch (StatusRuntimeException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to subscribe task push notification config: "); - } - } - - /** - * Ensure tenant is set, using agent default if not provided in request - * - * @param request the initial request. - * @return the updated request with the tenant set. - */ - private MessageSendParams createRequestWithTenant(MessageSendParams request) { - return MessageSendParams.builder() - .configuration(request.configuration()) - .message(request.message()) - .metadata(request.metadata()) - .tenant(resolveTenant(request.tenant())) - .build(); - } - - @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - GetExtendedAgentCardRequest request = GetExtendedAgentCardRequest.newBuilder() - .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, request, agentCard, context); - - try { - A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); - io.a2a.grpc.AgentCard response = stubWithMetadata.getExtendedAgentCard(request); - - return FromProto.agentCard(response); - } catch (StatusRuntimeException | StatusException e) { - throw GrpcErrorMapper.mapGrpcError(e, "Failed to get extended agent card: "); - } - } - - @Override - public void close() { - } - - private io.a2a.grpc.SendMessageRequest createGrpcSendMessageRequest(MessageSendParams messageSendParams, @Nullable ClientCallContext context) { - return ToProto.sendMessageRequest(messageSendParams); - } - - /** - * Creates gRPC metadata from ClientCallContext headers. - * Extracts headers like X-A2A-Extensions and sets them as gRPC metadata. - * - * @param context the client call context containing headers, may be null - * @param payloadAndHeaders the payload and headers wrapper, may be null - * @return the gRPC metadata - */ - private Metadata createGrpcMetadata(@Nullable ClientCallContext context, @Nullable PayloadAndHeaders payloadAndHeaders) { - Metadata metadata = new Metadata(); - - if (context != null && context.getHeaders() != null) { - // Set X-A2A-Version header if present - String versionHeader = context.getHeaders().get(A2AHeaders.X_A2A_VERSION); - if (versionHeader != null) { - metadata.put(VERSION_KEY, versionHeader); - } - - // Set X-A2A-Extensions header if present - String extensionsHeader = context.getHeaders().get(A2AHeaders.X_A2A_EXTENSIONS); - if (extensionsHeader != null) { - metadata.put(EXTENSIONS_KEY, extensionsHeader); - } - - // Add other headers as needed in the future - } - if (payloadAndHeaders != null && payloadAndHeaders.getHeaders() != null) { - // Handle all headers from interceptors (including auth headers) - for (Map.Entry headerEntry : payloadAndHeaders.getHeaders().entrySet()) { - String headerName = headerEntry.getKey(); - String headerValue = headerEntry.getValue(); - - if (headerValue != null) { - // Use static key for common Authorization header, create dynamic keys for others - if (AuthInterceptor.AUTHORIZATION.equals(headerName)) { - metadata.put(AUTHORIZATION_METADATA_KEY, headerValue); - } else { - // Create a metadata key dynamically for API keys and other custom headers - Metadata.Key metadataKey = Metadata.Key.of(headerName, Metadata.ASCII_STRING_MARSHALLER); - metadata.put(metadataKey, headerValue); - } - } - } - } - - return metadata; - } - - /** - * Creates a blocking stub with metadata attached from the ClientCallContext. - * - * @param context the client call context - * @param payloadAndHeaders the payloadAndHeaders after applying any interceptors - * @return blocking stub with metadata interceptor - */ - private A2AServiceBlockingV2Stub createBlockingStubWithMetadata(@Nullable ClientCallContext context, - PayloadAndHeaders payloadAndHeaders) { - Metadata metadata = createGrpcMetadata(context, payloadAndHeaders); - return blockingStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata)); - } - - /** - * Creates an async stub with metadata attached from the ClientCallContext. - * - * @param context the client call context - * @param payloadAndHeaders the payloadAndHeaders after applying any interceptors - * @return async stub with metadata interceptor - */ - private A2AServiceStub createAsyncStubWithMetadata(@Nullable ClientCallContext context, - PayloadAndHeaders payloadAndHeaders) { - Metadata metadata = createGrpcMetadata(context, payloadAndHeaders); - return asyncStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(metadata)); - } - - private PayloadAndHeaders applyInterceptors(String methodName, Object payload, - AgentCard agentCard, @Nullable ClientCallContext clientCallContext) { - PayloadAndHeaders payloadAndHeaders = new PayloadAndHeaders(payload, - clientCallContext != null ? clientCallContext.getHeaders() : null); - if (interceptors != null && !interceptors.isEmpty()) { - for (ClientCallInterceptor interceptor : interceptors) { - payloadAndHeaders = interceptor.intercept(methodName, payloadAndHeaders.getPayload(), - payloadAndHeaders.getHeaders(), agentCard, clientCallContext); - } - } - return payloadAndHeaders; - } - -} diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java deleted file mode 100644 index 605f7abb0..000000000 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java +++ /dev/null @@ -1,112 +0,0 @@ -package io.a2a.client.transport.grpc; - -import java.util.function.Function; - -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.util.Assert; -import io.grpc.Channel; - -/** - * Configuration for the gRPC transport protocol. - *

- * This configuration class allows customization of the gRPC channel factory used for - * communication with A2A agents. Unlike other transports, gRPC requires a channel factory - * to be explicitly provided - there is no default implementation. - *

- * Channel Factory Requirement: You must provide a {@code Function} - * that creates gRPC channels from agent URLs. This gives you full control over channel - * configuration including connection pooling, TLS, load balancing, and interceptors. - *

- * Basic usage with ManagedChannel: - *

{@code
- * // Simple insecure channel for development
- * Function channelFactory = url -> {
- *     String target = extractTarget(url); // e.g., "localhost:9999"
- *     return ManagedChannelBuilder.forTarget(target)
- *         .usePlaintext()
- *         .build();
- * };
- *
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .build();
- *
- * Client client = Client.builder(agentCard)
- *     .withTransport(GrpcTransport.class, config)
- *     .build();
- * }
- *

- * Production configuration with TLS and timeouts: - *

{@code
- * Function channelFactory = url -> {
- *     String target = extractTarget(url);
- *     return ManagedChannelBuilder.forTarget(target)
- *         .useTransportSecurity()
- *         .keepAliveTime(30, TimeUnit.SECONDS)
- *         .idleTimeout(5, TimeUnit.MINUTES)
- *         .maxInboundMessageSize(10 * 1024 * 1024) // 10MB
- *         .build();
- * };
- *
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .build();
- * }
- *

- * With load balancing and connection pooling: - *

{@code
- * Function channelFactory = url -> {
- *     String target = extractTarget(url);
- *     return ManagedChannelBuilder.forTarget(target)
- *         .defaultLoadBalancingPolicy("round_robin")
- *         .maxInboundMessageSize(50 * 1024 * 1024)
- *         .keepAliveTime(30, TimeUnit.SECONDS)
- *         .keepAliveTimeout(10, TimeUnit.SECONDS)
- *         .build();
- * };
- * }
- *

- * With interceptors: - *

{@code
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .addInterceptor(new LoggingInterceptor())
- *     .addInterceptor(new AuthInterceptor(apiKey))
- *     .build();
- * }
- *

- * Channel Lifecycle: The channel factory creates channels on-demand when the client - * connects to an agent. You are responsible for shutting down channels when the client is - * closed. Consider using {@code ManagedChannel.shutdown()} in a cleanup hook. - * - * @see GrpcTransportConfigBuilder - * @see GrpcTransport - * @see io.a2a.client.transport.spi.ClientTransportConfig - * @see io.grpc.ManagedChannelBuilder - */ -public class GrpcTransportConfig extends ClientTransportConfig { - - private final Function channelFactory; - - /** - * Create a gRPC transport configuration with a custom channel factory. - *

- * Consider using {@link GrpcTransportConfigBuilder} instead for a more fluent API. - * - * @param channelFactory function to create gRPC channels from agent URLs (must not be null) - * @throws IllegalArgumentException if channelFactory is null - */ - public GrpcTransportConfig(Function channelFactory) { - Assert.checkNotNullParam("channelFactory", channelFactory); - this.channelFactory = channelFactory; - } - - /** - * Get the configured channel factory. - * - * @return the channel factory function - */ - public Function getChannelFactory() { - return this.channelFactory; - } -} \ No newline at end of file diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java deleted file mode 100644 index 9ffcc1285..000000000 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java +++ /dev/null @@ -1,209 +0,0 @@ -package io.a2a.client.transport.grpc; - -import java.util.function.Function; - -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; -import io.a2a.util.Assert; -import io.grpc.Channel; -import org.jspecify.annotations.Nullable; - -/** - * Builder for creating {@link GrpcTransportConfig} instances. - *

- * This builder provides a fluent API for configuring the gRPC transport protocol. - * Unlike other transports, gRPC requires a channel factory to be explicitly provided - - * the {@link #channelFactory(Function)} method must be called before {@link #build()}. - *

- * The channel factory gives you complete control over gRPC channel configuration: - *

    - *
  • Connection management: Connection pooling, keep-alive settings
  • - *
  • Security: TLS configuration, client certificates
  • - *
  • Performance: Message size limits, compression, load balancing
  • - *
  • Timeouts: Deadline configuration, idle timeout
  • - *
  • Interceptors: Request/response transformation, authentication
  • - *
- *

- * Basic development setup (insecure): - *

{@code
- * // Simple channel for local development
- * Function channelFactory = url -> {
- *     // Extract "localhost:9999" from "http://localhost:9999"
- *     String target = url.replaceAll("^https?://", "");
- *     return ManagedChannelBuilder.forTarget(target)
- *         .usePlaintext()  // No TLS
- *         .build();
- * };
- *
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .build();
- *
- * Client client = Client.builder(agentCard)
- *     .withTransport(GrpcTransport.class, config)
- *     .build();
- * }
- *

- * Production setup with TLS and connection pooling: - *

{@code
- * Function channelFactory = url -> {
- *     String target = extractTarget(url);
- *     return ManagedChannelBuilder.forTarget(target)
- *         .useTransportSecurity()  // Enable TLS
- *         .keepAliveTime(30, TimeUnit.SECONDS)
- *         .keepAliveTimeout(10, TimeUnit.SECONDS)
- *         .idleTimeout(5, TimeUnit.MINUTES)
- *         .maxInboundMessageSize(10 * 1024 * 1024)  // 10MB messages
- *         .build();
- * };
- *
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .build();
- * }
- *

- * With custom SSL certificates: - *

{@code
- * SslContext sslContext = GrpcSslContexts.forClient()
- *     .trustManager(new File("ca.crt"))
- *     .keyManager(new File("client.crt"), new File("client.key"))
- *     .build();
- *
- * Function channelFactory = url -> {
- *     String target = extractTarget(url);
- *     return NettyChannelBuilder.forTarget(target)
- *         .sslContext(sslContext)
- *         .build();
- * };
- *
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .build();
- * }
- *

- * With load balancing and health checks: - *

{@code
- * Function channelFactory = url -> {
- *     String target = extractTarget(url);
- *     return ManagedChannelBuilder.forTarget(target)
- *         .defaultLoadBalancingPolicy("round_robin")
- *         .enableRetry()
- *         .maxRetryAttempts(3)
- *         .build();
- * };
- *
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .build();
- * }
- *

- * With A2A interceptors: - *

{@code
- * GrpcTransportConfig config = new GrpcTransportConfigBuilder()
- *     .channelFactory(channelFactory)
- *     .addInterceptor(new LoggingInterceptor())
- *     .addInterceptor(new MetricsInterceptor())
- *     .addInterceptor(new AuthenticationInterceptor(apiKey))
- *     .build();
- * }
- *

- * Direct usage in ClientBuilder: - *

{@code
- * // Channel factory inline
- * Client client = Client.builder(agentCard)
- *     .withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder()
- *         .channelFactory(url -> ManagedChannelBuilder
- *             .forTarget(extractTarget(url))
- *             .usePlaintext()
- *             .build())
- *         .addInterceptor(loggingInterceptor))
- *     .build();
- * }
- *

- * Channel Lifecycle Management: - *

{@code
- * // Store channels for cleanup
- * Map channels = new ConcurrentHashMap<>();
- *
- * Function channelFactory = url -> {
- *     return channels.computeIfAbsent(url, u -> {
- *         String target = extractTarget(u);
- *         return ManagedChannelBuilder.forTarget(target)
- *             .usePlaintext()
- *             .build();
- *     });
- * };
- *
- * // Cleanup when done
- * Runtime.getRuntime().addShutdownHook(new Thread(() -> {
- *     channels.values().forEach(ManagedChannel::shutdown);
- * }));
- * }
- * - * @see GrpcTransportConfig - * @see GrpcTransport - * @see io.a2a.client.transport.spi.ClientTransportConfigBuilder - * @see io.grpc.ManagedChannelBuilder - * @see io.grpc.Channel - */ -public class GrpcTransportConfigBuilder extends ClientTransportConfigBuilder { - - private @Nullable Function channelFactory; - - /** - * Set the channel factory for creating gRPC channels. - *

- * This method is required - {@link #build()} will throw {@link IllegalStateException} - * if the channel factory is not set. - *

- * The factory function receives the agent's URL (e.g., "http://localhost:9999") and must - * return a configured {@link Channel}. You are responsible for: - *

    - *
  • Extracting the target address from the URL
  • - *
  • Configuring TLS and security settings
  • - *
  • Setting connection pool and timeout parameters
  • - *
  • Managing channel lifecycle and shutdown
  • - *
- *

- * Example: - *

{@code
-     * Function factory = url -> {
-     *     String target = url.replaceAll("^https?://", "");
-     *     return ManagedChannelBuilder.forTarget(target)
-     *         .usePlaintext()
-     *         .build();
-     * };
-     *
-     * builder.channelFactory(factory);
-     * }
- * - * @param channelFactory function to create gRPC channels from agent URLs (must not be null) - * @return this builder for method chaining - * @throws IllegalArgumentException if channelFactory is null - */ - public GrpcTransportConfigBuilder channelFactory(Function channelFactory) { - Assert.checkNotNullParam("channelFactory", channelFactory); - - this.channelFactory = channelFactory; - - return this; - } - - /** - * Build the gRPC transport configuration. - *

- * The channel factory must have been set via {@link #channelFactory(Function)} before - * calling this method. Any configured interceptors are transferred to the configuration. - * - * @return the configured gRPC transport configuration - * @throws IllegalStateException if the channel factory was not set - */ - @Override - public GrpcTransportConfig build() { - if (channelFactory == null) { - throw new IllegalStateException("channelFactory must be set"); - } - GrpcTransportConfig config = new GrpcTransportConfig(channelFactory); - config.setInterceptors(interceptors); - return config; - } -} \ No newline at end of file diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportProvider.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportProvider.java deleted file mode 100644 index d331d0874..000000000 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.a2a.client.transport.grpc; - -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; -import io.grpc.Channel; - -/** - * Provider for gRPC transport implementation. - */ -public class GrpcTransportProvider implements ClientTransportProvider { - - @Override - public GrpcTransport create(GrpcTransportConfig grpcTransportConfig, AgentCard agentCard, AgentInterface agentInterface) throws A2AClientException { - // not making use of the interceptors for gRPC for now - - Channel channel = grpcTransportConfig.getChannelFactory().apply(agentInterface.url()); - if (channel != null) { - return new GrpcTransport(channel, agentCard, agentInterface.tenant(), grpcTransportConfig.getInterceptors()); - } - - throw new A2AClientException("Missing required GrpcTransportConfig"); - } - - @Override - public String getTransportProtocol() { - return TransportProtocol.GRPC.asString(); - } - - @Override - public Class getTransportProtocolClass() { - return GrpcTransport.class; - } -} diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/package-info.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/package-info.java deleted file mode 100644 index c0c12ccb5..000000000 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.client.transport.grpc; - -import org.jspecify.annotations.NullMarked; \ No newline at end of file diff --git a/client/transport/grpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider b/client/transport/grpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider deleted file mode 100644 index 86d4fa7e5..000000000 --- a/client/transport/grpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.transport.grpc.GrpcTransportProvider \ No newline at end of file diff --git a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java b/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java deleted file mode 100644 index 864e406d2..000000000 --- a/client/transport/grpc/src/test/java/io/a2a/client/transport/grpc/GrpcErrorMapperTest.java +++ /dev/null @@ -1,194 +0,0 @@ -package io.a2a.client.transport.grpc; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.a2a.spec.A2AClientException; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; -import io.grpc.Status; -import io.grpc.StatusRuntimeException; -import org.junit.jupiter.api.Test; - -/** - * Tests for GrpcErrorMapper - verifies correct unmarshalling of gRPC errors to A2A error types - */ -public class GrpcErrorMapperTest { - - @Test - public void testExtensionSupportRequiredErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with ExtensionSupportRequiredError in description - String errorMessage = "ExtensionSupportRequiredError: Extension required: https://example.com/test-extension"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify the result - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(ExtensionSupportRequiredError.class, result.getCause()); - - ExtensionSupportRequiredError extensionError = (ExtensionSupportRequiredError) result.getCause(); - assertNotNull(extensionError.getMessage()); - assertTrue(extensionError.getMessage().contains("https://example.com/test-extension")); - assertTrue(result.getMessage().contains(errorMessage)); - } - - @Test - public void testVersionNotSupportedErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with VersionNotSupportedError in description - String errorMessage = "VersionNotSupportedError: Version 2.0 is not supported"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify the result - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(VersionNotSupportedError.class, result.getCause()); - - VersionNotSupportedError versionError = (VersionNotSupportedError) result.getCause(); - assertNotNull(versionError.getMessage()); - assertTrue(versionError.getMessage().contains("Version 2.0 is not supported")); - } - - @Test - public void testExtendedCardNotConfiguredErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with ExtendedCardNotConfiguredError in description - String errorMessage = "ExtendedCardNotConfiguredError: Extended card not configured for this agent"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify the result - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(ExtendedAgentCardNotConfiguredError.class, result.getCause()); - - ExtendedAgentCardNotConfiguredError extendedCardError = (ExtendedAgentCardNotConfiguredError) result.getCause(); - assertNotNull(extendedCardError.getMessage()); - assertTrue(extendedCardError.getMessage().contains("Extended card not configured")); - } - - @Test - public void testTaskNotFoundErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with TaskNotFoundError in description - String errorMessage = "TaskNotFoundError: Task task-123 not found"; - StatusRuntimeException grpcException = Status.NOT_FOUND - .withDescription(errorMessage) - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify the result - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(TaskNotFoundError.class, result.getCause()); - } - - @Test - public void testUnsupportedOperationErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with UnsupportedOperationError in description - String errorMessage = "UnsupportedOperationError: Operation not supported"; - StatusRuntimeException grpcException = Status.UNIMPLEMENTED - .withDescription(errorMessage) - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify the result - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(UnsupportedOperationError.class, result.getCause()); - } - - @Test - public void testInvalidParamsErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with InvalidParamsError in description - String errorMessage = "InvalidParamsError: Invalid parameters provided"; - StatusRuntimeException grpcException = Status.INVALID_ARGUMENT - .withDescription(errorMessage) - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify the result - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(InvalidParamsError.class, result.getCause()); - } - - @Test - public void testContentTypeNotSupportedErrorUnmarshalling() { - // Create a gRPC StatusRuntimeException with ContentTypeNotSupportedError in description - String errorMessage = "ContentTypeNotSupportedError: Content type application/xml not supported"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify the result - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(ContentTypeNotSupportedError.class, result.getCause()); - - ContentTypeNotSupportedError contentTypeError = (ContentTypeNotSupportedError) result.getCause(); - assertNotNull(contentTypeError.getMessage()); - assertTrue(contentTypeError.getMessage().contains("Content type application/xml not supported")); - } - - @Test - public void testFallbackToStatusCodeMapping() { - // Create a gRPC StatusRuntimeException without specific error type in description - StatusRuntimeException grpcException = Status.NOT_FOUND - .withDescription("Generic not found error") - .asRuntimeException(); - - // Map the gRPC error to A2A error - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException); - - // Verify fallback to status code mapping - assertNotNull(result); - assertNotNull(result.getCause()); - assertInstanceOf(TaskNotFoundError.class, result.getCause()); - } - - @Test - public void testCustomErrorPrefix() { - // Create a gRPC StatusRuntimeException - String errorMessage = "ExtensionSupportRequiredError: Extension required: https://example.com/ext"; - StatusRuntimeException grpcException = Status.FAILED_PRECONDITION - .withDescription(errorMessage) - .asRuntimeException(); - - // Map with custom error prefix - String customPrefix = "Custom Error: "; - A2AClientException result = GrpcErrorMapper.mapGrpcError(grpcException, customPrefix); - - // Verify custom prefix is used - assertNotNull(result); - assertTrue(result.getMessage().startsWith(customPrefix)); - assertInstanceOf(ExtensionSupportRequiredError.class, result.getCause()); - } -} diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml deleted file mode 100644 index f0ffd3407..000000000 --- a/client/transport/jsonrpc/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../../pom.xml - - a2a-java-sdk-client-transport-jsonrpc - jar - - Java SDK A2A Client Transport: JSONRPC - Java SDK for the Agent2Agent Protocol (A2A) - JSONRPC Client Transport - - - - ${project.groupId} - a2a-java-sdk-http-client - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - - - ${project.groupId} - a2a-java-sdk-common - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-spec-grpc - - - com.google.protobuf - protobuf-java-util - provided - - - com.google.protobuf - protobuf-java - provided - - - org.junit.jupiter - junit-jupiter-api - test - - - - org.mock-server - mockserver-netty - test - - - - \ No newline at end of file diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java deleted file mode 100644 index 9b8af4ea2..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java +++ /dev/null @@ -1,374 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; -import static io.a2a.util.Assert.checkNotNullParam; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -import com.google.protobuf.MessageOrBuilder; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.client.transport.jsonrpc.sse.SSEEventListener; -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; -import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.wrappers.A2AResponse; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -public class JSONRPCTransport implements ClientTransport { - - private final A2AHttpClient httpClient; - private final AgentInterface agentInterface; - private final @Nullable List interceptors; - private final @Nullable AgentCard agentCard; - - public JSONRPCTransport(String agentUrl) { - this(null, null, new AgentInterface("JSONRPC", agentUrl), null); - } - - public JSONRPCTransport(AgentCard agentCard) { - this(null, agentCard, Utils.getFavoriteInterface(agentCard), null); - } - - public JSONRPCTransport(@Nullable A2AHttpClient httpClient, @Nullable AgentCard agentCard, - AgentInterface agentInterface, @Nullable List interceptors) { - this.httpClient = httpClient == null ? A2AHttpClientFactory.create() : httpClient; - this.agentCard = agentCard; - this.agentInterface = agentInterface; - this.interceptors = interceptors; - } - - @Override - public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_MESSAGE_METHOD, ProtoUtils.ToProto.sendMessageRequest(request), - agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SEND_MESSAGE_METHOD); - SendMessageResponse response = unmarshalResponse(httpResponseBody, SEND_MESSAGE_METHOD); - return response.getResult(); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to send message: " + e, e); - } - } - - @Override - public void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, - @Nullable Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - checkNotNullParam("eventConsumer", eventConsumer); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_STREAMING_MESSAGE_METHOD, - ProtoUtils.ToProto.sendMessageRequest(request), agentCard, context); - - final AtomicReference> ref = new AtomicReference<>(); - SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); - - try { - A2AHttpClient.PostBuilder builder = createPostBuilder(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SEND_STREAMING_MESSAGE_METHOD); - ref.set(builder.postAsyncSSE( - msg -> sseEventListener.onMessage(msg, ref.get()), - throwable -> sseEventListener.onError(throwable, ref.get()), - () -> { - // Signal normal stream completion to error handler (null error means success) - sseEventListener.onComplete(); - })); - } catch (IOException e) { - throw new A2AClientException("Failed to send streaming message request: " + e, e); - } catch (InterruptedException e) { - throw new A2AClientException("Send streaming message request timed out: " + e, e); - } catch (JsonProcessingException e) { - throw new A2AClientException("Failed to process JSON for streaming message request: " + e, e); - } - } - - @Override - public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_METHOD, ProtoUtils.ToProto.getTaskRequest(request), - agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, GET_TASK_METHOD); - GetTaskResponse response = unmarshalResponse(httpResponseBody, GET_TASK_METHOD); - return response.getResult(); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to get task: " + e, e); - } - } - - @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(CANCEL_TASK_METHOD, ProtoUtils.ToProto.cancelTaskRequest(request), - agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, CANCEL_TASK_METHOD); - CancelTaskResponse response = unmarshalResponse(httpResponseBody, CANCEL_TASK_METHOD); - return response.getResult(); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to cancel task: " + e, e); - } - } - - @Override - public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_METHOD, ProtoUtils.ToProto.listTasksParams(request), - agentCard, context); - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, LIST_TASK_METHOD); - ListTasksResponse response = unmarshalResponse(httpResponseBody, LIST_TASK_METHOD); - return response.getResult(); - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to list tasks: " + e, e); - } - } - - @Override - public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - ProtoUtils.ToProto.createTaskPushNotificationConfigRequest(request), agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - CreateTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - return response.getResult(); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to set task push notification config: " + e, e); - } - } - - @Override - public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - ProtoUtils.ToProto.getTaskPushNotificationConfigRequest(request), agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - GetTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - return response.getResult(); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to get task push notification config: " + e, e); - } - } - - @Override - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - ProtoUtils.ToProto.listTaskPushNotificationConfigRequest(request), agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - ListTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - return response.getResult(); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to list task push notification configs: " + e, e); - } - } - - @Override - public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - ProtoUtils.ToProto.deleteTaskPushNotificationConfigRequest(request), agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - DeleteTaskPushNotificationConfigResponse response = unmarshalResponse(httpResponseBody, DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - // Response validated (no error), but no result to return - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to delete task push notification configs: " + e, e); - } - } - - @Override - public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - checkNotNullParam("eventConsumer", eventConsumer); - checkNotNullParam("errorConsumer", errorConsumer); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, ProtoUtils.ToProto.subscribeToTaskRequest(request), agentCard, context); - - AtomicReference> ref = new AtomicReference<>(); - SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); - - try { - A2AHttpClient.PostBuilder builder = createPostBuilder(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SUBSCRIBE_TO_TASK_METHOD); - ref.set(builder.postAsyncSSE( - msg -> sseEventListener.onMessage(msg, ref.get()), - throwable -> sseEventListener.onError(throwable, ref.get()), - () -> { - // Signal normal stream completion to error handler (null error means success) - sseEventListener.onComplete(); - })); - } catch (IOException e) { - throw new A2AClientException("Failed to send task resubscription request: " + e, e); - } catch (InterruptedException e) { - throw new A2AClientException("Task resubscription request timed out: " + e, e); - } catch (JsonProcessingException e) { - throw new A2AClientException("Failed to process JSON for task resubscription request: " + e, e); - } - } - - @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - try { - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, - ProtoUtils.ToProto.extendedAgentCard(), agentCard, context); - - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, ""), payloadAndHeaders, GET_EXTENDED_AGENT_CARD_METHOD); - GetExtendedAgentCardResponse response = unmarshalResponse(httpResponseBody, GET_EXTENDED_AGENT_CARD_METHOD); - return response.getResult(); - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to get authenticated extended agent card: " + e, e); - } - } catch(A2AClientError e){ - throw new A2AClientException("Failed to get agent card: " + e, e); - } - } - - @Override - public void close() { - // no-op - } - - private PayloadAndHeaders applyInterceptors(String methodName, @Nullable Object payload, - @Nullable AgentCard agentCard, @Nullable ClientCallContext clientCallContext) { - PayloadAndHeaders payloadAndHeaders = new PayloadAndHeaders(payload, getHttpHeaders(clientCallContext)); - if (interceptors != null && ! interceptors.isEmpty()) { - for (ClientCallInterceptor interceptor : interceptors) { - payloadAndHeaders = interceptor.intercept(methodName, payloadAndHeaders.getPayload(), - payloadAndHeaders.getHeaders(), agentCard, clientCallContext); - } - } - return payloadAndHeaders; - } - - private String sendPostRequest(String url, PayloadAndHeaders payloadAndHeaders, String method) throws IOException, InterruptedException, JsonProcessingException { - A2AHttpClient.PostBuilder builder = createPostBuilder(url, payloadAndHeaders,method); - A2AHttpResponse response = builder.post(); - if (!response.success()) { - throw new IOException("Request failed " + response.status()); - } - return response.body(); - } - - private A2AHttpClient.PostBuilder createPostBuilder(String url, PayloadAndHeaders payloadAndHeaders, String method) throws JsonProcessingException { - A2AHttpClient.PostBuilder postBuilder = httpClient.createPost() - .url(url) - .addHeader("Content-Type", "application/json") - .body(JSONRPCUtils.toJsonRPCRequest(null, method, (MessageOrBuilder) payloadAndHeaders.getPayload())); - - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - postBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - - return postBuilder; - } - - /** - * Unmarshals a JSON-RPC response string into a type-safe response object. - *

- * This method parses the JSON-RPC response body and returns the appropriate - * response type based on the method parameter. If the response contains an error, - * an A2AClientException is thrown. - * - * @param the expected response type, must extend JSONRPCResponse - * @param response the JSON-RPC response body as a string - * @param method the method name used to determine the response type - * @return the parsed response object of type T - * @throws A2AClientException if the response contains an error or parsing fails - * @throws JsonProcessingException if the JSON cannot be processed - */ - @SuppressWarnings("unchecked") - private > T unmarshalResponse(String response, String method) - throws A2AClientException, JsonProcessingException { - A2AResponse value = JSONRPCUtils.parseResponseBody(response, method); - A2AError error = value.getError(); - if (error != null) { - throw new A2AClientException(error.getMessage() + (error.getData() != null ? ": " + error.getData() : ""), error); - } - // Safe cast: JSONRPCUtils.parseResponseBody returns the correct concrete type based on method - return (T) value; - } - - private @Nullable Map getHttpHeaders(@Nullable ClientCallContext context) { - return context != null ? context.getHeaders() : null; - } -} \ No newline at end of file diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java deleted file mode 100644 index 909ff079e..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java +++ /dev/null @@ -1,84 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.transport.spi.ClientTransportConfig; -import org.jspecify.annotations.Nullable; - -/** - * Configuration for the JSON-RPC transport protocol. - *

- * This configuration class allows customization of the HTTP client used for JSON-RPC - * communication with A2A agents. If no HTTP client is specified, the default JDK-based - * implementation is used. - *

- * Basic usage: - *

{@code
- * // Use default HTTP client
- * JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder()
- *     .build();
- *
- * Client client = Client.builder(agentCard)
- *     .withTransport(JSONRPCTransport.class, config)
- *     .build();
- * }
- *

- * Custom HTTP client: - *

{@code
- * // Custom HTTP client with timeouts
- * A2AHttpClient customClient = new CustomHttpClient()
- *     .withConnectTimeout(Duration.ofSeconds(10))
- *     .withReadTimeout(Duration.ofSeconds(30));
- *
- * JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder()
- *     .httpClient(customClient)
- *     .build();
- * }
- *

- * With interceptors: - *

{@code
- * JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder()
- *     .httpClient(customClient)
- *     .addInterceptor(new LoggingInterceptor())
- *     .addInterceptor(new AuthInterceptor("Bearer token"))
- *     .build();
- * }
- * - * @see JSONRPCTransportConfigBuilder - * @see JSONRPCTransport - * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient - */ -public class JSONRPCTransportConfig extends ClientTransportConfig { - - private final @Nullable A2AHttpClient httpClient; - - /** - * Create a JSON-RPC transport configuration with the default HTTP client. - *

- * The default JDK-based HTTP client will be used. Consider using - * {@link JSONRPCTransportConfigBuilder} instead for a more fluent API. - */ - public JSONRPCTransportConfig() { - this.httpClient = null; - } - - /** - * Create a JSON-RPC transport configuration with a custom HTTP client. - *

- * Consider using {@link JSONRPCTransportConfigBuilder} instead for a more fluent API. - * - * @param httpClient the HTTP client to use for JSON-RPC requests - */ - public JSONRPCTransportConfig(A2AHttpClient httpClient) { - this.httpClient = httpClient; - } - - /** - * Get the configured HTTP client. - * - * @return the HTTP client, or {@code null} if using the default - */ - public @Nullable A2AHttpClient getHttpClient() { - return httpClient; - } -} diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java deleted file mode 100644 index 7f73b4c2d..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfigBuilder.java +++ /dev/null @@ -1,120 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; -import org.jspecify.annotations.Nullable; - -/** - * Builder for creating {@link JSONRPCTransportConfig} instances. - *

- * This builder provides a fluent API for configuring the JSON-RPC transport protocol. - * All configuration options are optional - if not specified, sensible defaults are used: - *

    - *
  • HTTP client: Auto-selected via {@link A2AHttpClientFactory} (prefers Vert.x, falls back to JDK)
  • - *
  • Interceptors: None
  • - *
- *

- * Basic usage: - *

{@code
- * // Minimal configuration (uses all defaults)
- * JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder()
- *     .build();
- *
- * Client client = Client.builder(agentCard)
- *     .withTransport(JSONRPCTransport.class, config)
- *     .build();
- * }
- *

- * Custom HTTP client: - *

{@code
- * // Configure custom HTTP client for connection pooling, timeouts, etc.
- * A2AHttpClient httpClient = new ApacheHttpClient()
- *     .withConnectionTimeout(Duration.ofSeconds(10))
- *     .withMaxConnections(50);
- *
- * JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder()
- *     .httpClient(httpClient)
- *     .build();
- * }
- *

- * With interceptors: - *

{@code
- * JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder()
- *     .addInterceptor(new LoggingInterceptor())
- *     .addInterceptor(new MetricsInterceptor())
- *     .addInterceptor(new RetryInterceptor(3))
- *     .build();
- * }
- *

- * Direct usage in ClientBuilder: - *

{@code
- * // Can pass builder directly to withTransport()
- * Client client = Client.builder(agentCard)
- *     .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()
- *         .httpClient(customClient)
- *         .addInterceptor(loggingInterceptor))
- *     .build();
- * }
- * - * @see JSONRPCTransportConfig - * @see JSONRPCTransport - * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient - */ -public class JSONRPCTransportConfigBuilder extends ClientTransportConfigBuilder { - - private @Nullable A2AHttpClient httpClient; - - /** - * Set the HTTP client to use for JSON-RPC requests. - *

- * Custom HTTP clients can provide: - *

    - *
  • Connection pooling and reuse
  • - *
  • Custom timeout configuration
  • - *
  • SSL/TLS configuration
  • - *
  • Proxy support
  • - *
  • Custom header handling
  • - *
- *

- * If not specified, a client is auto-selected via {@link A2AHttpClientFactory}. - *

- * Example: - *

{@code
-     * A2AHttpClient client = new CustomHttpClient()
-     *     .withConnectTimeout(Duration.ofSeconds(5))
-     *     .withReadTimeout(Duration.ofSeconds(30))
-     *     .withConnectionPool(10, 50);
-     *
-     * builder.httpClient(client);
-     * }
- * - * @param httpClient the HTTP client to use - * @return this builder for method chaining - */ - public JSONRPCTransportConfigBuilder httpClient(A2AHttpClient httpClient) { - this.httpClient = httpClient; - return this; - } - - /** - * Build the JSON-RPC transport configuration. - *

- * If no HTTP client was configured, one is auto-selected via {@link A2AHttpClientFactory}. - * Any configured interceptors are transferred to the configuration. - * - * @return the configured JSON-RPC transport configuration - */ - @Override - public JSONRPCTransportConfig build() { - // No HTTP client provided, use factory to get best available implementation - if (httpClient == null) { - httpClient = A2AHttpClientFactory.create(); - } - - JSONRPCTransportConfig config = new JSONRPCTransportConfig(httpClient); - config.setInterceptors(this.interceptors); - return config; - } -} diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportProvider.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportProvider.java deleted file mode 100644 index 2dc1a9733..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportProvider.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; -import org.jspecify.annotations.Nullable; - -public class JSONRPCTransportProvider implements ClientTransportProvider { - - @Override - public JSONRPCTransport create(@Nullable JSONRPCTransportConfig clientTransportConfig, AgentCard agentCard, AgentInterface agentInterface) throws A2AClientException { - JSONRPCTransportConfig currentClientTransportConfig = clientTransportConfig; - if (currentClientTransportConfig == null) { - currentClientTransportConfig = new JSONRPCTransportConfig(A2AHttpClientFactory.create()); - } - return new JSONRPCTransport(currentClientTransportConfig.getHttpClient(), agentCard, agentInterface, currentClientTransportConfig.getInterceptors()); - } - - @Override - public String getTransportProtocol() { - return TransportProtocol.JSONRPC.asString(); - } - - @Override - public Class getTransportProtocolClass() { - return JSONRPCTransport.class; - } -} diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/package-info.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/package-info.java deleted file mode 100644 index 3fc8e35ec..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.jsonrpc; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java deleted file mode 100644 index 2c61d082e..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.a2a.client.transport.jsonrpc.sse; - -import java.util.concurrent.Future; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import io.a2a.client.transport.spi.sse.AbstractSSEEventListener; -import io.a2a.grpc.StreamResponse; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.spec.A2AError; -import io.a2a.spec.StreamingEventKind; -import org.jspecify.annotations.Nullable; - -/** - * JSON-RPC transport implementation of SSE event listener. - * Handles parsing of JSON-RPC formatted messages from SSE streams. - */ -public class SSEEventListener extends AbstractSSEEventListener { - - private static final Logger log = Logger.getLogger(SSEEventListener.class.getName()); - private volatile boolean completed = false; - - public SSEEventListener(Consumer eventHandler, - @Nullable Consumer errorHandler) { - super(eventHandler, errorHandler); - } - - @Override - public void onMessage(String message, @Nullable Future completableFuture) { - parseAndHandleMessage(message, completableFuture); - } - - public void onComplete() { - // Idempotent: only signal completion once, even if called multiple times - if (completed) { - log.fine("SSEEventListener.onComplete() called again - ignoring (already completed)"); - return; - } - completed = true; - - // Signal normal stream completion (null error means successful completion) - log.fine("SSEEventListener.onComplete() called - signaling successful stream completion"); - if (getErrorHandler() != null) { - log.fine("Calling errorHandler.accept(null) to signal successful completion"); - getErrorHandler().accept(null); - } else { - log.warning("errorHandler is null, cannot signal completion"); - } - } - - /** - * Parses a JSON-RPC message and delegates to the base class for event handling. - * - * @param message The raw JSON-RPC message string - * @param future Optional future for controlling the SSE connection - */ - private void parseAndHandleMessage(String message, @Nullable Future future) { - try { - StreamResponse response = JSONRPCUtils.parseResponseEvent(message); - StreamingEventKind event = ProtoUtils.FromProto.streamingEventKind(response); - - // Delegate to base class for common event handling and auto-close logic - handleEvent(event, future); - } catch (A2AError error) { - if (getErrorHandler() != null) { - getErrorHandler().accept(error); - } - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/package-info.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/package-info.java deleted file mode 100644 index 956b8992a..000000000 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.jsonrpc.sse; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/jsonrpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider b/client/transport/jsonrpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider deleted file mode 100644 index b2904cb45..000000000 --- a/client/transport/jsonrpc/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.transport.jsonrpc.JSONRPCTransportProvider \ No newline at end of file diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java deleted file mode 100644 index 1f28d9201..000000000 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java +++ /dev/null @@ -1,171 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.SEND_MESSAGE_STREAMING_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonStreamingMessages.TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Part; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; -import org.mockserver.matchers.MatchType; -import org.mockserver.model.JsonBody; - -public class JSONRPCTransportStreamingTest { - - private ClientAndServer server; - - @BeforeEach - public void setUp() { - server = new ClientAndServer(4001); - } - - @AfterEach - public void tearDown() { - server.stop(); - } - - @Test - public void testSendStreamingMessageParams() { - // The goal here is just to verify the correct parameters are being used - // This is a unit test of the parameter construction, not the streaming itself - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("test message"))) - .contextId("context-test") - .messageId("message-test") - .build(); - - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(false) - .build(); - - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - assertNotNull(params); - assertEquals(message, params.message()); - assertEquals(configuration, params.configuration()); - assertEquals(Message.Role.ROLE_USER, params.message().role()); - assertEquals("test message", ((TextPart) params.message().parts().get(0)).text()); - } - - @Test - public void testA2AClientSendStreamingMessage() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SEND_MESSAGE_STREAMING_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody(SEND_MESSAGE_STREAMING_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("tell me some jokes"))) - .contextId("context-1234") - .messageId("message-1234") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(false) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - AtomicReference receivedEvent = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - Consumer eventHandler = event -> { - receivedEvent.set(event); - latch.countDown(); - }; - Consumer errorHandler = error -> {}; - client.sendMessageStreaming(params, eventHandler, errorHandler, null); - - boolean eventReceived = latch.await(10, TimeUnit.SECONDS); - assertTrue(eventReceived); - assertNotNull(receivedEvent.get()); - } - - @Test - public void testA2AClientSubscribeToTask() throws Exception { - this.server.when(request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(TASK_SUBSCRIPTION_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody(TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - TaskIdParams taskIdParams = new TaskIdParams("task-1234"); - - AtomicReference receivedEvent = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - Consumer eventHandler = event -> { - receivedEvent.set(event); - latch.countDown(); - }; - Consumer errorHandler = error -> {}; - client.subscribeToTask(taskIdParams, eventHandler, errorHandler, null); - - boolean eventReceived = latch.await(10, TimeUnit.SECONDS); - assertTrue(eventReceived); - - StreamingEventKind eventKind = receivedEvent.get();; - assertNotNull(eventKind); - assertInstanceOf(Task.class, eventKind); - Task task = (Task) eventKind; - assertEquals("2", task.id()); - assertEquals("context-1234", task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - List artifacts = task.artifacts(); - assertEquals(1, artifacts.size()); - Artifact artifact = artifacts.get(0); - assertEquals("artifact-1", artifact.artifactId()); - assertEquals("joke", artifact.name()); - Part part = artifact.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) part).text()); - } -} \ No newline at end of file diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java deleted file mode 100644 index 0bd42a978..000000000 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportTest.java +++ /dev/null @@ -1,703 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.CANCEL_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.GET_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_ERROR_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_ERROR_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; -import static io.a2a.client.transport.jsonrpc.JsonMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.VersionNotSupportedError; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.Artifact; -import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.DataPart; -import io.a2a.spec.EventKind; -import io.a2a.spec.FileContent; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; -import io.a2a.util.Utils; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; -import org.mockserver.matchers.MatchType; -import org.mockserver.model.JsonBody; - -public class JSONRPCTransportTest { - - private ClientAndServer server; - - @BeforeEach - public void setUp() { - server = new ClientAndServer(4001); - } - - @AfterEach - public void tearDown() { - server.stop(); - } - - @Test - public void testA2AClientSendMessage() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SEND_MESSAGE_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(SEND_MESSAGE_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("tell me a joke"))) - .contextId("context-1234") - .messageId("message-1234") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - EventKind result = client.sendMessage(params, null); - assertInstanceOf(Task.class, result); - Task task = (Task) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertNotNull(task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED,task.status().state()); - assertEquals(1, task.artifacts().size()); - Artifact artifact = task.artifacts().get(0); - assertEquals("artifact-1", artifact.artifactId()); - assertEquals("joke", artifact.name()); - assertEquals(1, artifact.parts().size()); - Part part = artifact.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) part).text()); - assertTrue(task.metadata().isEmpty()); - } - - @Test - public void testA2AClientSendMessageWithMessageResponse() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("tell me a joke"))) - .contextId("context-1234") - .messageId("message-1234") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - EventKind result = client.sendMessage(params, null); - assertInstanceOf(Message.class, result); - Message agentMessage = (Message) result; - assertEquals(Message.Role.ROLE_AGENT, agentMessage.role()); - Part part = agentMessage.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) part).text()); - assertEquals("msg-456", agentMessage.messageId()); - } - - - @Test - public void testA2AClientSendMessageWithError() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SEND_MESSAGE_WITH_ERROR_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(SEND_MESSAGE_ERROR_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("tell me a joke"))) - .contextId("context-1234") - .messageId("message-1234") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - try { - client.sendMessage(params, null); - fail(); // should not reach here - } catch (A2AClientException e) { - assertTrue(e.getMessage().contains("Invalid parameters: \"Hello world\""),e.getMessage()); - } - } - - @Test - public void testA2AClientGetTask() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(GET_TASK_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(GET_TASK_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Task task = client.getTask(new TaskQueryParams("de38c76d-d54c-436c-8b9f-4c2703648d64", - 10), null); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - assertEquals(1, task.artifacts().size()); - Artifact artifact = task.artifacts().get(0); - assertEquals(1, artifact.parts().size()); - assertEquals("artifact-1", artifact.artifactId()); - Part part = artifact.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) part).text()); - assertTrue(task.metadata().isEmpty()); - List history = task.history(); - assertNotNull(history); - assertEquals(1, history.size()); - Message message = history.get(0); - assertEquals(Message.Role.ROLE_USER, message.role()); - List> parts = message.parts(); - assertNotNull(parts); - assertEquals(3, parts.size()); - part = parts.get(0); - assertTrue(part instanceof TextPart); - assertEquals("tell me a joke", ((TextPart)part).text()); - part = parts.get(1); - assertTrue(part instanceof FilePart); - FileContent filePart = ((FilePart) part).file(); - assertEquals("file:///path/to/file.txt", ((FileWithUri) filePart).uri()); - assertEquals("text/plain", filePart.mimeType()); - part = parts.get(2); - assertTrue(part instanceof FilePart); - filePart = ((FilePart) part).file(); - assertEquals("aGVsbG8=", ((FileWithBytes) filePart).bytes()); - assertEquals("hello.txt", filePart.name()); - assertTrue(task.metadata().isEmpty()); - } - - @Test - public void testA2AClientCancelTask() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(CANCEL_TASK_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(CANCEL_TASK_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Task task = client.cancelTask(new TaskIdParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", task.contextId()); - assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); - assertTrue(task.metadata().isEmpty()); - } - - @Test - public void testA2AClientGetTaskPushNotificationConfig() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - TaskPushNotificationConfig taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64", "c295ea44-7543-4f78-b524-7a38915ad6e4"), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertEquals("jwt", authenticationInfo.scheme()); - } - - @Test - public void testA2AClientCreateTaskPushNotificationConfig() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration( - new TaskPushNotificationConfig("de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4") - .url("https://example.com/callback") - .authentication(new AuthenticationInfo("jwt", null)) - .build(), ""), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertEquals("jwt", authenticationInfo.scheme()); - } - - @Test - public void testA2AClientGetExtendedAgentCard() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - ) - .respond( - response() - .withStatusCode(200) - .withBody(GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - AgentCard agentCard = client.getExtendedAgentCard(null); - assertEquals("GeoSpatial Route Planner Agent Extended", agentCard.name()); - assertEquals("Extended description", agentCard.description()); - assertEquals("https://georoute-agent.example.com/a2a/v1", Utils.getFavoriteInterface(agentCard).url()); - assertEquals("Example Geo Services Inc.", agentCard.provider().organization()); - assertEquals("https://www.examplegeoservices.com", agentCard.provider().url()); - assertEquals("1.2.0", agentCard.version()); - assertEquals("https://docs.examplegeoservices.com/georoute-agent/api", agentCard.documentationUrl()); - assertTrue(agentCard.capabilities().streaming()); - assertTrue(agentCard.capabilities().pushNotifications()); - assertTrue(agentCard.capabilities().extendedAgentCard()); - Map securitySchemes = agentCard.securitySchemes(); - assertNotNull(securitySchemes); - OpenIdConnectSecurityScheme google = (OpenIdConnectSecurityScheme) securitySchemes.get("google"); - assertEquals("https://accounts.google.com/.well-known/openid-configuration", google.openIdConnectUrl()); - List security = agentCard.securityRequirements(); - assertEquals(1, security.size()); - Map> securityMap = security.get(0).schemes(); - List scopes = securityMap.get("google"); - List expectedScopes = List.of("openid", "profile", "email"); - assertEquals(expectedScopes, scopes); - List defaultInputModes = List.of("application/json", "text/plain"); - assertEquals(defaultInputModes, agentCard.defaultInputModes()); - List defaultOutputModes = List.of("application/json", "image/png"); - assertEquals(defaultOutputModes, agentCard.defaultOutputModes()); - List skills = agentCard.skills(); - assertEquals("route-optimizer-traffic", skills.get(0).id()); - assertEquals("Traffic-Aware Route Optimizer", skills.get(0).name()); - assertEquals("Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", skills.get(0).description()); - List tags = List.of("maps", "routing", "navigation", "directions", "traffic"); - assertEquals(tags, skills.get(0).tags()); - List examples = List.of("Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}"); - assertEquals(examples, skills.get(0).examples()); - assertEquals(defaultInputModes, skills.get(0).inputModes()); - List outputModes = List.of("application/json", "application/vnd.geo+json", "text/html"); - assertEquals(outputModes, skills.get(0).outputModes()); - assertEquals("custom-map-generator", skills.get(1).id()); - assertEquals("Personalized Map Generator", skills.get(1).name()); - assertEquals("Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", skills.get(1).description()); - tags = List.of("maps", "customization", "visualization", "cartography"); - assertEquals(tags, skills.get(1).tags()); - examples = List.of("Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location."); - assertEquals(examples, skills.get(1).examples()); - List inputModes = List.of("application/json"); - assertEquals(inputModes, skills.get(1).inputModes()); - outputModes = List.of("image/png", "image/jpeg", "application/json", "text/html"); - assertEquals(outputModes, skills.get(1).outputModes()); - assertEquals("skill-extended", skills.get(2).id()); - assertEquals("Extended Skill", skills.get(2).name()); - assertEquals("This is an extended skill.", skills.get(2).description()); - assertEquals(List.of("extended"), skills.get(2).tags()); - assertEquals("https://georoute-agent.example.com/icon.png", agentCard.iconUrl()); - assertEquals(CURRENT_PROTOCOL_VERSION, agentCard.supportedInterfaces().get(0).protocolVersion()); - } - - @Test - public void testA2AClientSendMessageWithFilePart() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of( - new TextPart("analyze this image"), - new FilePart(new FileWithUri("image/jpeg", null, "file:///path/to/image.jpg")) - )) - .contextId("context-1234") - .messageId("message-1234-with-file") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - EventKind result = client.sendMessage(params, null); - assertInstanceOf(Task.class, result); - Task task = (Task) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertNotNull(task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - assertEquals(1, task.artifacts().size()); - Artifact artifact = task.artifacts().get(0); - assertEquals("artifact-1", artifact.artifactId()); - assertEquals("image-analysis", artifact.name()); - assertEquals(1, artifact.parts().size()); - Part part = artifact.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("This is an image of a cat sitting on a windowsill.", ((TextPart) part).text()); - assertFalse(task.metadata().isEmpty()); - assertEquals(1, task.metadata().size()); - assertEquals("metadata-test", task.metadata().get("test")); - } - - @Test - public void testA2AClientSendMessageWithDataPart() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - - Map data = new HashMap<>(); - data.put("temperature", 25.5); - data.put("humidity", 60.2); - data.put("location", "San Francisco"); - data.put("timestamp", "2024-01-15T10:30:00Z"); - - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of( - new TextPart("process this data"), - new DataPart(data) - )) - .contextId("context-1234") - .messageId("message-1234-with-data") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - EventKind result = client.sendMessage(params, null); - assertInstanceOf(Task.class, result); - Task task = (Task) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertNotNull(task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - assertEquals(1, task.artifacts().size()); - Artifact artifact = task.artifacts().get(0); - assertEquals("artifact-1", artifact.artifactId()); - assertEquals("data-analysis", artifact.name()); - assertEquals(1, artifact.parts().size()); - Part part = artifact.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco.", ((TextPart) part).text()); - assertTrue(task.metadata().isEmpty()); - } - - @Test - public void testA2AClientSendMessageWithMixedParts() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/") - .withBody(JsonBody.json(SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - - ) - .respond( - response() - .withStatusCode(200) - .withBody(SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - - Map data = new HashMap<>(); - data.put("chartType", "bar"); - data.put("dataPoints", List.of(10, 20, 30, 40)); - data.put("labels", List.of("Q1", "Q2", "Q3", "Q4")); - - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of( - new TextPart("analyze this data and image"), - new FilePart(new FileWithBytes("image/png", "chart.png", "aGVsbG8=")), - new DataPart(data) - )) - .contextId("context-1234") - .messageId("message-1234-with-mixed") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - EventKind result = client.sendMessage(params, null); - assertInstanceOf(Task.class, result); - Task task = (Task) result; - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertNotNull(task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - assertEquals(1, task.artifacts().size()); - Artifact artifact = task.artifacts().get(0); - assertEquals("artifact-1", artifact.artifactId()); - assertEquals("mixed-analysis", artifact.name()); - assertEquals(1, artifact.parts().size()); - Part part = artifact.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40].", ((TextPart) part).text()); - assertTrue(task.metadata().isEmpty()); - } - - /** - * Test that ExtensionSupportRequiredError is properly unmarshalled from JSON-RPC error response. - */ - @Test - public void testExtensionSupportRequiredErrorUnmarshalling() throws Exception { - // Mock server returns JSON-RPC error with code -32008 (EXTENSION_SUPPORT_REQUIRED_ERROR) - String errorResponseBody = """ - { - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32008, - "message": "Extension required: https://example.com/test-extension" - } - } - """; - - this.server.when( - request() - .withMethod("POST") - .withPath("/") - ) - .respond( - response() - .withStatusCode(200) - .withBody(errorResponseBody) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("test message"))) - .contextId("context-test") - .messageId("message-test") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - // Should throw A2AClientException with ExtensionSupportRequiredError as cause - try { - client.sendMessage(params, null); - fail("Expected A2AClientException to be thrown"); - } catch (A2AClientException e) { - // Verify the cause is ExtensionSupportRequiredError - assertInstanceOf(ExtensionSupportRequiredError.class, e.getCause()); - ExtensionSupportRequiredError extensionError = (ExtensionSupportRequiredError) e.getCause(); - assertTrue(extensionError.getMessage().contains("https://example.com/test-extension")); - } - } - - /** - * Test that VersionNotSupportedError is properly unmarshalled from JSON-RPC error response. - */ - @Test - public void testVersionNotSupportedErrorUnmarshalling() throws Exception { - // Mock server returns JSON-RPC error with code -32009 (VERSION_NOT_SUPPORTED_ERROR) - String errorResponseBody = """ - { - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32009, - "message": "Protocol version 2.0 is not supported. This agent supports version 1.0" - } - } - """; - - this.server.when( - request() - .withMethod("POST") - .withPath("/") - ) - .respond( - response() - .withStatusCode(200) - .withBody(errorResponseBody) - ); - - JSONRPCTransport client = new JSONRPCTransport("http://localhost:4001"); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("test message"))) - .contextId("context-test") - .messageId("message-test") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(true) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - // Should throw A2AClientException with VersionNotSupportedError as cause - try { - client.sendMessage(params, null); - fail("Expected A2AClientException to be thrown"); - } catch (A2AClientException e) { - // Verify the cause is VersionNotSupportedError - assertInstanceOf(VersionNotSupportedError.class, e.getCause()); - VersionNotSupportedError versionError = (VersionNotSupportedError) e.getCause(); - assertTrue(versionError.getMessage().contains("2.0")); - assertTrue(versionError.getMessage().contains("1.0")); - } - } -} \ No newline at end of file diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java deleted file mode 100644 index b55c0f9d1..000000000 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java +++ /dev/null @@ -1,724 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; - -/** - * Request and response messages used by the tests. These have been created following examples from - * the A2A sample messages. - */ -public class JsonMessages { - - static final String AGENT_CARD = """ - { - "name": "GeoSpatial Route Planner Agent", - "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", - "supportedInterfaces" : [ - {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "JSONRPC", "tenant": ""}, - {"url": "https://georoute-agent.example.com/a2a/grpc", "protocolBinding": "GRPC", "tenant": ""}, - {"url": "https://georoute-agent.example.com/a2a/json", "protocolBinding": "HTTP+JSON", "tenant": ""} - ], - "provider": { - "organization": "Example Geo Services Inc.", - "url": "https://www.examplegeoservices.com" - }, - "iconUrl": "https://georoute-agent.example.com/icon.png", - "version": "1.2.0", - "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", - "capabilities": { - "streaming": true, - "pushNotifications": true, - "extendedAgentCard": false - }, - "securitySchemes": { - "google": { - "openIdConnectSecurityScheme": { - "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" - } - } - }, - "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], - "defaultInputModes": ["application/json", "text/plain"], - "defaultOutputModes": ["application/json", "image/png"], - "skills": [ - { - "id": "route-optimizer-traffic", - "name": "Traffic-Aware Route Optimizer", - "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", - "tags": ["maps", "routing", "navigation", "directions", "traffic"], - "examples": [ - "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" - ], - "inputModes": ["application/json", "text/plain"], - "outputModes": [ - "application/json", - "application/vnd.geo+json", - "text/html" - ] - }, - { - "id": "custom-map-generator", - "name": "Personalized Map Generator", - "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", - "tags": ["maps", "customization", "visualization", "cartography"], - "examples": [ - "Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." - ], - "inputModes": ["application/json"], - "outputModes": [ - "image/png", - "image/jpeg", - "application/json", - "text/html" - ] - } - ], - "signatures": [ - { - "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", - "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" - } - ] - }"""; - - static final String SEND_MESSAGE_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "params":{ - "message":{ - "messageId":"message-1234", - "contextId":"context-1234", - "role":"ROLE_USER", - "parts":[ - { - "text":"tell me a joke" - } - ], - "metadata":{ - - } - } - } - }"""; - - static final String SEND_MESSAGE_TEST_RESPONSE = """ - { - "jsonrpc":"2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result":{ - "task":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "status":{ - "state":"TASK_STATE_COMPLETED" - }, - "artifacts":[ - { - "artifactId":"artifact-1", - "name":"joke", - "parts":[ - { - "text":"Why did the chicken cross the road? To get to the other side!" - } - ] - } - ], - "metadata":{ - - } - } - } - }"""; - - static final String SEND_MESSAGE_TEST_REQUEST_WITH_MESSAGE_RESPONSE = """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "params":{ - "message":{ - "messageId":"message-1234", - "contextId":"context-1234", - "role":"ROLE_USER", - "parts":[ - { - "text":"tell me a joke" - } - ], - "metadata":{ - } - }, - "configuration":{ - "acceptedOutputModes":[ - "text" - ], - "blocking":true - }, - "metadata":{ - - } - } - }"""; - - static final String SEND_MESSAGE_TEST_RESPONSE_WITH_MESSAGE_RESPONSE = """ - { - "jsonrpc":"2.0", - "id":1, - "result":{ - "message": { - "messageId":"msg-456", - "contextId":"context-1234", - "role":"ROLE_AGENT", - "parts":[ - { - "text":"Why did the chicken cross the road? To get to the other side!" - } - ], - "metadata":{ - } - } - } - }"""; - - static final String SEND_MESSAGE_WITH_ERROR_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "params":{ - "message":{ - "messageId":"message-1234", - "contextId":"context-1234", - "role":"ROLE_USER", - "parts":[ - { - "text":"tell me a joke" - } - ], - "metadata":{ - - } - }, - "configuration":{ - "acceptedOutputModes":[ - "text" - ], - "blocking":true - }, - "metadata":{ - - } - } - }"""; - - static final String SEND_MESSAGE_ERROR_TEST_RESPONSE = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "error": { - "code": -32702, - "message": "Invalid parameters", - "data": "Hello world" - } - }"""; - - static final String GET_TASK_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"GetTask", - "params":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "historyLength":10 - } - } - """; - - static final String GET_TASK_TEST_RESPONSE = """ - { - "jsonrpc":"2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "status":{ - "state":"TASK_STATE_COMPLETED" - }, - "artifacts":[ - { - "artifactId":"artifact-1", - "parts":[ - { - "text":"Why did the chicken cross the road? To get to the other side!" - } - ] - } - ], - "history":[ - { - "role":"ROLE_USER", - "parts":[ - { - "text":"tell me a joke" - }, - { - "url":"file:///path/to/file.txt", - "mediaType":"text/plain" - }, - { - "raw":"aGVsbG8=", - "filename":"hello.txt" - } - ], - "messageId":"message-123" - } - ], - "metadata":{ - - } - } - } - """; - - static final String CANCEL_TASK_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"CancelTask", - "params":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64" - } - } - """; - - static final String CANCEL_TASK_TEST_RESPONSE = """ - { - "jsonrpc":"2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "status":{ - "state":"TASK_STATE_CANCELED" - }, - "metadata":{ - - } - } - } - """; - - static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"GetTaskPushNotificationConfig", - "params":{ - "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "id":"c295ea44-7543-4f78-b524-7a38915ad6e4" - } - }"""; - - static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result": { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "c295ea44-7543-4f78-b524-7a38915ad6e4", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - } - } - """; - - static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"CreateTaskPushNotificationConfig", - "params":{ - "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "configId":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "config":{ - "url":"https://example.com/callback", - "authentication":{ - "scheme":"jwt" - } - } - } - }"""; - - static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result": { - "taskId":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "id":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - } - } - """; - - static final String SEND_MESSAGE_WITH_FILE_PART_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "params":{ - "message":{ - "messageId":"message-1234-with-file", - "contextId":"context-1234", - "role":"ROLE_USER", - "parts":[ - { - "text":"analyze this image" - }, - { - "url":"file:///path/to/image.jpg", - "mediaType":"image/jpeg" - } - ], - "metadata":{ - - } - }, - "configuration":{ - "acceptedOutputModes":[ - "text" - ], - "blocking":true - }, - "metadata":{ - - } - } - }"""; - - static final String SEND_MESSAGE_WITH_FILE_PART_TEST_RESPONSE = """ - { - "jsonrpc":"2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result":{ - "task":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "status":{ - "state":"TASK_STATE_COMPLETED" - }, - "artifacts":[ - { - "artifactId":"artifact-1", - "name":"image-analysis", - "parts":[ - { - "text":"This is an image of a cat sitting on a windowsill." - } - ] - } - ], - "metadata":{ - "test":"metadata-test" - } - } - } - }"""; - - static final String SEND_MESSAGE_WITH_DATA_PART_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "params":{ - "message":{ - "messageId":"message-1234-with-data", - "contextId":"context-1234", - "role":"ROLE_USER", - "parts":[ - { - "text":"process this data" - }, - { - "data":{ - "temperature":25.5, - "humidity":60.2, - "location":"San Francisco", - "timestamp":"2024-01-15T10:30:00Z" - } - } - ], - "metadata":{ - - } - }, - "configuration":{ - "acceptedOutputModes":[ - "text" - ], - "blocking":true - }, - "metadata":{ - - } - } - }"""; - - static final String SEND_MESSAGE_WITH_DATA_PART_TEST_RESPONSE = """ - { - "jsonrpc":"2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result":{ - "task":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "status":{ - "state":"TASK_STATE_COMPLETED" - }, - "artifacts":[ - { - "artifactId":"artifact-1", - "name":"data-analysis", - "parts":[ - { - "text":"Processed weather data: Temperature is 25.5°C, humidity is 60.2% in San Francisco." - } - ] - } - ], - "metadata":{ - - } - } - } - }"""; - - static final String SEND_MESSAGE_WITH_MIXED_PARTS_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "params":{ - "message":{ - "messageId":"message-1234-with-mixed", - "contextId":"context-1234", - "role":"ROLE_USER", - "parts":[ - { - "text":"analyze this data and image" - }, - { - "raw":"aGVsbG8=", - "mediaType":"image/png", - "filename":"chart.png" - }, - { - "data":{ - "chartType":"bar", - "dataPoints":[10.0, 20.0, 30.0, 40.0], - "labels":["Q1", "Q2", "Q3", "Q4"] - } - } - ], - "metadata":{ - - } - }, - "configuration":{ - "acceptedOutputModes":[ - "text" - ], - "blocking":true - }, - "metadata":{ - - } - } - }"""; - - static final String SEND_MESSAGE_WITH_MIXED_PARTS_TEST_RESPONSE = """ - { - "jsonrpc":"2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "result":{ - "task":{ - "id":"de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId":"c295ea44-7543-4f78-b524-7a38915ad6e4", - "status":{ - "state":"TASK_STATE_COMPLETED" - }, - "artifacts":[ - { - "artifactId":"artifact-1", - "name":"mixed-analysis", - "parts":[ - { - "text":"Analyzed chart image and data: Bar chart showing quarterly data with values [10, 20, 30, 40]." - } - ] - } - ], - "metadata":{ - - } - } - } - }"""; - - static final String GET_AUTHENTICATED_EXTENDED_AGENT_CARD_REQUEST = """ - { - "jsonrpc": "2.0", - "method": "GetExtendedAgentCard" - } - """; - - static final String GET_AUTHENTICATED_EXTENDED_AGENT_CARD_RESPONSE = """ - { - "jsonrpc": "2.0", - "id": "1", - "result": { - "name": "GeoSpatial Route Planner Agent Extended", - "description": "Extended description", - "supportedInterfaces": [ - {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "JSONRPC", "tenant": ""} - ], - "provider": { - "organization": "Example Geo Services Inc.", - "url": "https://www.examplegeoservices.com" - }, - "iconUrl": "https://georoute-agent.example.com/icon.png", - "version": "1.2.0", - "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", - "capabilities": { - "streaming": true, - "pushNotifications": true, - "extendedAgentCard": true - }, - "securitySchemes": { - "google": { - "openIdConnectSecurityScheme": { - "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" - } - } - }, - "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], - "defaultInputModes": ["application/json", "text/plain"], - "defaultOutputModes": ["application/json", "image/png"], - "skills": [ - { - "id": "route-optimizer-traffic", - "name": "Traffic-Aware Route Optimizer", - "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", - "tags": ["maps", "routing", "navigation", "directions", "traffic"], - "examples": [ - "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" - ], - "inputModes": ["application/json", "text/plain"], - "outputModes": [ - "application/json", - "application/vnd.geo+json", - "text/html" - ] - }, - { - "id": "custom-map-generator", - "name": "Personalized Map Generator", - "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", - "tags": ["maps", "customization", "visualization", "cartography"], - "examples": [ - "Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." - ], - "inputModes": ["application/json"], - "outputModes": [ - "image/png", - "image/jpeg", - "application/json", - "text/html" - ] - }, - { - "id": "skill-extended", - "name": "Extended Skill", - "description": "This is an extended skill.", - "tags": ["extended"] - } - ], - "signatures": [ - { - "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdUI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", - "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" - } - ] - } - }"""; - - static final String AGENT_CARD_SUPPORTS_EXTENDED = """ - { - "name": "GeoSpatial Route Planner Agent", - "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", - "supportedInterfaces": [ - {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "JSONRPC"} - ], - "provider": { - "organization": "Example Geo Services Inc.", - "url": "https://www.examplegeoservices.com" - }, - "iconUrl": "https://georoute-agent.example.com/icon.png", - "version": "1.2.0", - "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", - "capabilities": { - "streaming": true, - "pushNotifications": true, - "extendedAgentCard": true - }, - "securitySchemes": { - "google": { - "openIdConnectSecurityScheme": { - "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" - } - } - }, - "security": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], - "defaultInputModes": ["application/json", "text/plain"], - "defaultOutputModes": ["application/json", "image/png"], - "skills": [ - { - "id": "route-optimizer-traffic", - "name": "Traffic-Aware Route Optimizer", - "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", - "tags": ["maps", "routing", "navigation", "directions", "traffic"], - "examples": [ - "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" - ], - "inputModes": ["application/json", "text/plain"], - "outputModes": [ - "application/json", - "application/vnd.geo+json", - "text/html" - ] - }, - { - "id": "custom-map-generator", - "name": "Personalized Map Generator", - "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", - "tags": ["maps", "customization", "visualization", "cartography"], - "examples": [ - "Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." - ], - "inputModes": ["application/json"], - "outputModes": [ - "image/png", - "image/jpeg", - "application/json", - "text/html" - ] - } - ] - }"""; -} diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java deleted file mode 100644 index 39f2d7859..000000000 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonStreamingMessages.java +++ /dev/null @@ -1,157 +0,0 @@ -package io.a2a.client.transport.jsonrpc; - -/** - * Contains JSON strings for testing SSE streaming. - */ -public class JsonStreamingMessages { - - public static final String STREAMING_TASK_EVENT = """ - data: { - "jsonrpc": "2.0", - "id": "1234", - "result": { - "task": { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_WORKING" - } - } - } - } - """; - - - public static final String STREAMING_MESSAGE_EVENT = """ - data: { - "jsonrpc": "2.0", - "id": "1234", - "result": { - "message": { - "role": "ROLE_AGENT", - "messageId": "msg-123", - "contextId": "context-456", - "parts": [ - { - "text": "Hello, world!" - } - ] - } - } - }"""; - - public static final String STREAMING_STATUS_UPDATE_EVENT = """ - data: { - "jsonrpc": "2.0", - "id": "1234", - "result": { - "statusUpdate": { - "taskId": "1", - "contextId": "2", - "status": { - "state": "TASK_STATE_SUBMITTED" - } - } - } - }"""; - - public static final String STREAMING_STATUS_UPDATE_EVENT_FINAL = """ - data: { - "jsonrpc": "2.0", - "id": "1234", - "result": { - "statusUpdate": { - "taskId": "1", - "contextId": "2", - "status": { - "state": "TASK_STATE_COMPLETED" - } - } - } - }"""; - - public static final String STREAMING_ARTIFACT_UPDATE_EVENT = """ - data: { - "jsonrpc": "2.0", - "id": "1234", - "result": { - "artifactUpdate": { - "taskId": "1", - "contextId": "2", - "append": false, - "lastChunk": true, - "artifact": { - "artifactId": "artifact-1", - "parts": [ - { - "text": "Why did the chicken cross the road? To get to the other side!" - } - ] - } - } - } - }"""; - - public static final String STREAMING_ERROR_EVENT = """ - data: { - "jsonrpc": "2.0", - "id": "1234", - "error": { - "code": -32602, - "message": "Invalid parameters", - "data": "Missing required field" - } - }"""; - - public static final String SEND_MESSAGE_STREAMING_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"SendStreamingMessage", - "params":{ - "message":{ - "messageId":"message-1234", - "contextId":"context-1234", - "role":"ROLE_USER", - "parts":[ - { - "text":"tell me some jokes" - } - ], - "metadata":{ - - } - }, - "configuration":{ - "acceptedOutputModes":[ - "text" - ] - }, - "metadata":{ - - } - } - }"""; - - static final String SEND_MESSAGE_STREAMING_TEST_RESPONSE = - """ - event: message - data: {"jsonrpc":"2.0","id":1,"result":{"task":{"id":"2","contextId":"context-1234","status":{"state":"TASK_STATE_COMPLETED"},"artifacts":[{"artifactId":"artifact-1","name":"joke","parts":[{"text":"Why did the chicken cross the road? To get to the other side!"}]}],"metadata":{}}}} - - """; - - static final String TASK_SUBSCRIPTION_REQUEST_TEST_RESPONSE = - """ - event: message - data: {"jsonrpc":"2.0","id":1,"result":{"task":{"id":"2","contextId":"context-1234","status":{"state":"TASK_STATE_COMPLETED"},"artifacts":[{"artifactId":"artifact-1","name":"joke","parts":[{"text":"Why did the chicken cross the road? To get to the other side!"}]}],"metadata":{}}}} - - """; - - public static final String TASK_SUBSCRIPTION_TEST_REQUEST = """ - { - "jsonrpc":"2.0", - "method":"SubscribeToTask", - "params":{ - "id":"task-1234" - } - }"""; -} \ No newline at end of file diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java deleted file mode 100644 index e9e74d12f..000000000 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java +++ /dev/null @@ -1,284 +0,0 @@ -package io.a2a.client.transport.jsonrpc.sse; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import io.a2a.client.transport.jsonrpc.JsonStreamingMessages; -import io.a2a.spec.A2AError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; - -public class SSEEventListenerTest { - - @Test - public void testOnEventWithTaskResult() throws Exception { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // Parse the task event JSON - String eventData = JsonStreamingMessages.STREAMING_TASK_EVENT.substring( - JsonStreamingMessages.STREAMING_TASK_EVENT.indexOf("{")); - - // Call the onEvent method directly - listener.onMessage(eventData, null); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof Task); - Task task = (Task) receivedEvent.get(); - assertEquals("task-123", task.id()); - assertEquals("context-456", task.contextId()); - assertEquals(TaskState.TASK_STATE_WORKING, task.status().state()); - } - - @Test - public void testOnEventWithMessageResult() throws Exception { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // Parse the message event JSON - String eventData = JsonStreamingMessages.STREAMING_MESSAGE_EVENT.substring( - JsonStreamingMessages.STREAMING_MESSAGE_EVENT.indexOf("{")); - - // Call onEvent method - listener.onMessage(eventData, null); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof Message); - Message message = (Message) receivedEvent.get(); - assertEquals(Message.Role.ROLE_AGENT, message.role()); - assertEquals("msg-123", message.messageId()); - assertEquals("context-456", message.contextId()); - assertEquals(1, message.parts().size()); - assertTrue(message.parts().get(0) instanceof TextPart); - assertEquals("Hello, world!", ((TextPart) message.parts().get(0)).text()); - } - - @Test - public void testOnEventWithTaskStatusUpdateEventEvent() throws Exception { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // Parse the message event JSON - String eventData = JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT.substring( - JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT.indexOf("{")); - - // Call onEvent method - listener.onMessage(eventData, null); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); - TaskStatusUpdateEvent taskStatusUpdateEvent = (TaskStatusUpdateEvent) receivedEvent.get(); - assertEquals("1", taskStatusUpdateEvent.taskId()); - assertEquals("2", taskStatusUpdateEvent.contextId()); - assertFalse(taskStatusUpdateEvent.isFinal()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, taskStatusUpdateEvent.status().state()); - } - - @Test - public void testOnEventWithTaskArtifactUpdateEventEvent() throws Exception { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // Parse the message event JSON - String eventData = JsonStreamingMessages.STREAMING_ARTIFACT_UPDATE_EVENT.substring( - JsonStreamingMessages.STREAMING_ARTIFACT_UPDATE_EVENT.indexOf("{")); - - // Call onEvent method - listener.onMessage(eventData, null); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof TaskArtifactUpdateEvent); - - TaskArtifactUpdateEvent taskArtifactUpdateEvent = (TaskArtifactUpdateEvent) receivedEvent.get(); - assertEquals("1", taskArtifactUpdateEvent.taskId()); - assertEquals("2", taskArtifactUpdateEvent.contextId()); - assertFalse(taskArtifactUpdateEvent.append()); - assertTrue(taskArtifactUpdateEvent.lastChunk()); - Artifact artifact = taskArtifactUpdateEvent.artifact(); - assertEquals("artifact-1", artifact.artifactId()); - assertEquals(1, artifact.parts().size()); - assertTrue(artifact.parts().get(0) instanceof TextPart); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) artifact.parts().get(0)).text()); - } - - @Test - public void testOnEventWithError() throws Exception { - // Set up event handler - AtomicReference receivedError = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> {}, - error -> receivedError.set(error) - ); - - // Parse the error event JSON - String eventData = JsonStreamingMessages.STREAMING_ERROR_EVENT.substring( - JsonStreamingMessages.STREAMING_ERROR_EVENT.indexOf("{")); - - // Call onEvent method - listener.onMessage(eventData, null); - - // Verify the error was processed correctly - assertNotNull(receivedError.get()); - assertInstanceOf(A2AError.class, receivedError.get()); - A2AError jsonrpcError = (A2AError) receivedError.get(); - assertEquals(-32602, jsonrpcError.getCode()); - assertEquals("Invalid parameters", jsonrpcError.getMessage()); - assertEquals("\"Missing required field\"", jsonrpcError.getData()); - } - - @Test - public void testOnFailure() { - AtomicBoolean failureHandlerCalled = new AtomicBoolean(false); - SSEEventListener listener = new SSEEventListener( - event -> {}, - error -> failureHandlerCalled.set(true) - ); - - // Simulate a failure - CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onError(new RuntimeException("Test exception"), future); - - // Verify the failure handler was called - assertTrue(failureHandlerCalled.get()); - // Verify it got cancelled - assertTrue(future.cancelHandlerCalled); - } - - @Test - public void testFinalTaskStatusUpdateEventCancels() { - TaskStatus completedStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED); - // Use constructor since Builder doesn't have isFinal method - TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( - "1234", - completedStatus, - "xyz", - completedStatus.state().isFinal(), // Derive from state - null - ); - - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // Parse the message event JSON - String eventData = JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT_FINAL.substring( - JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT_FINAL.indexOf("{")); - - // Call onMessage with a cancellable future - CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(eventData, future); - - // Verify the event was received and processed - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); - TaskStatusUpdateEvent received = (TaskStatusUpdateEvent) receivedEvent.get(); - assertTrue(received.isFinal()); - - // Verify the future was cancelled (auto-close on final event) - assertTrue(future.cancelHandlerCalled); - } - - @Test - public void testOnEventWithFinalTaskStatusUpdateEventEventCancels() throws Exception { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // Parse the message event JSON - String eventData = JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT_FINAL.substring( - JsonStreamingMessages.STREAMING_STATUS_UPDATE_EVENT_FINAL.indexOf("{")); - - // Call onEvent method - CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(eventData, future); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); - TaskStatusUpdateEvent taskStatusUpdateEvent = (TaskStatusUpdateEvent) receivedEvent.get(); - assertEquals("1", taskStatusUpdateEvent.taskId()); - assertEquals("2", taskStatusUpdateEvent.contextId()); - assertTrue(taskStatusUpdateEvent.isFinal()); - assertEquals(TaskState.TASK_STATE_COMPLETED, taskStatusUpdateEvent.status().state()); - - assertTrue(future.cancelHandlerCalled); - } - - - private static class CancelCapturingFuture implements Future { - private boolean cancelHandlerCalled; - - public CancelCapturingFuture() { - } - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - cancelHandlerCalled = true; - return true; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return false; - } - - @Override - public Void get() throws InterruptedException, ExecutionException { - return null; - } - - @Override - public Void get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - return null; - } - } -} \ No newline at end of file diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml deleted file mode 100644 index ecdf7befd..000000000 --- a/client/transport/rest/pom.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../../pom.xml - - a2a-java-sdk-client-transport-rest - jar - - Java SDK A2A Client Transport: JSON+HTTP/REST - Java SDK for the Agent2Agent Protocol (A2A) - JSON+HTTP/REST Client Transport - - - - ${project.groupId} - a2a-java-sdk-common - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-spec-grpc - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - - - io.github.a2asdk - a2a-java-sdk-http-client - - - com.google.protobuf - protobuf-java-util - - - org.junit.jupiter - junit-jupiter-api - test - - - - org.mock-server - mockserver-netty - test - - - org.slf4j - slf4j-jdk14 - test - - - - \ No newline at end of file diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java deleted file mode 100644 index 92ce45416..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.a2a.client.transport.rest; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.google.gson.JsonObject; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; - -/** - * Utility class to A2AHttpResponse to appropriate A2A error types - */ -public class RestErrorMapper { - - public static A2AClientException mapRestError(A2AHttpResponse response) { - return RestErrorMapper.mapRestError(response.body(), response.status()); - } - - public static A2AClientException mapRestError(String body, int code) { - try { - if (body != null && !body.isBlank()) { - JsonObject node = JsonUtil.fromJson(body, JsonObject.class); - String className = node.has("error") ? node.get("error").getAsString() : ""; - String errorMessage = node.has("message") ? node.get("message").getAsString() : ""; - return mapRestError(className, errorMessage, code); - } - return mapRestError("", "", code); - } catch (JsonProcessingException ex) { - Logger.getLogger(RestErrorMapper.class.getName()).log(Level.SEVERE, null, ex); - return new A2AClientException("Failed to parse error response: " + ex.getMessage()); - } - } - - public static A2AClientException mapRestError(String className, String errorMessage, int code) { - return switch (className) { - case "io.a2a.spec.TaskNotFoundError" -> new A2AClientException(errorMessage, new TaskNotFoundError()); - case "io.a2a.spec.ExtendedCardNotConfiguredError" -> new A2AClientException(errorMessage, new ExtendedAgentCardNotConfiguredError(null, errorMessage, null)); - case "io.a2a.spec.ContentTypeNotSupportedError" -> new A2AClientException(errorMessage, new ContentTypeNotSupportedError(null, null, errorMessage)); - case "io.a2a.spec.InternalError" -> new A2AClientException(errorMessage, new InternalError(errorMessage)); - case "io.a2a.spec.InvalidAgentResponseError" -> new A2AClientException(errorMessage, new InvalidAgentResponseError(null, null, errorMessage)); - case "io.a2a.spec.InvalidParamsError" -> new A2AClientException(errorMessage, new InvalidParamsError()); - case "io.a2a.spec.InvalidRequestError" -> new A2AClientException(errorMessage, new InvalidRequestError()); - case "io.a2a.spec.JSONParseError" -> new A2AClientException(errorMessage, new JSONParseError()); - case "io.a2a.spec.MethodNotFoundError" -> new A2AClientException(errorMessage, new MethodNotFoundError()); - case "io.a2a.spec.PushNotificationNotSupportedError" -> new A2AClientException(errorMessage, new PushNotificationNotSupportedError()); - case "io.a2a.spec.TaskNotCancelableError" -> new A2AClientException(errorMessage, new TaskNotCancelableError()); - case "io.a2a.spec.UnsupportedOperationError" -> new A2AClientException(errorMessage, new UnsupportedOperationError()); - case "io.a2a.spec.ExtensionSupportRequiredError" -> new A2AClientException(errorMessage, new ExtensionSupportRequiredError(null, errorMessage, null)); - case "io.a2a.spec.VersionNotSupportedError" -> new A2AClientException(errorMessage, new VersionNotSupportedError(null, errorMessage, null)); - default -> new A2AClientException(errorMessage); - }; - } -} diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java deleted file mode 100644 index 0ec8f2eb1..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java +++ /dev/null @@ -1,485 +0,0 @@ -package io.a2a.client.transport.rest; - -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; -import static io.a2a.util.Assert.checkNotNullParam; - -import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.MessageOrBuilder; -import com.google.protobuf.util.JsonFormat; -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.client.transport.rest.sse.SSEEventListener; -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; -import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -public class RestTransport implements ClientTransport { - - private static final Logger log = Logger.getLogger(RestTransport.class.getName()); - private final A2AHttpClient httpClient; - private final AgentInterface agentInterface; - private @Nullable final List interceptors; - private final AgentCard agentCard; - - public RestTransport(AgentCard agentCard) { - this(null, agentCard, Utils.getFavoriteInterface(agentCard), null); - } - - public RestTransport(@Nullable A2AHttpClient httpClient, AgentCard agentCard, - AgentInterface agentInterface, @Nullable List interceptors) { - this.httpClient = httpClient == null ? A2AHttpClientFactory.create() : httpClient; - this.agentCard = agentCard; - this.agentInterface = agentInterface; - this.interceptors = interceptors; - } - - @Override - public EventKind sendMessage(MessageSendParams messageSendParams, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("messageSendParams", messageSendParams); - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(ProtoUtils.ToProto.sendMessageRequest(messageSendParams)); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_MESSAGE_METHOD, builder, agentCard, context); - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, messageSendParams.tenant()) + "/message:send", payloadAndHeaders); - io.a2a.grpc.SendMessageResponse.Builder responseBuilder = io.a2a.grpc.SendMessageResponse.newBuilder(); - JsonFormat.parser().merge(httpResponseBody, responseBuilder); - if (responseBuilder.hasMessage()) { - return ProtoUtils.FromProto.message(responseBuilder.getMessage()); - } - if (responseBuilder.hasTask()) { - return ProtoUtils.FromProto.task(responseBuilder.getTask()); - } - throw new A2AClientException("Failed to send message, wrong response:" + httpResponseBody); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to send message: " + e, e); - } - } - - @Override - public void sendMessageStreaming(MessageSendParams messageSendParams, Consumer eventConsumer, Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", messageSendParams); - checkNotNullParam("eventConsumer", eventConsumer); - checkNotNullParam("messageSendParams", messageSendParams); - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(ProtoUtils.ToProto.sendMessageRequest(messageSendParams)); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_STREAMING_MESSAGE_METHOD, builder, agentCard, context); - AtomicReference> ref = new AtomicReference<>(); - SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); - try { - A2AHttpClient.PostBuilder postBuilder = createPostBuilder(Utils.buildBaseUrl(agentInterface, messageSendParams.tenant()) + "/message:stream", payloadAndHeaders); - ref.set(postBuilder.postAsyncSSE( - msg -> sseEventListener.onMessage(msg, ref.get()), - throwable -> sseEventListener.onError(throwable, ref.get()), - () -> { - // We don't need to do anything special on completion - })); - } catch (IOException e) { - throw new A2AClientException("Failed to send streaming message request: " + e, e); - } catch (InterruptedException e) { - throw new A2AClientException("Send streaming message request timed out: " + e, e); - } catch (JsonProcessingException e) { - throw new A2AClientException("Failed to process JSON for streaming message request: " + e, e); - } - } - - @Override - public Task getTask(TaskQueryParams taskQueryParams, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("taskQueryParams", taskQueryParams); - io.a2a.grpc.GetTaskRequest.Builder builder = io.a2a.grpc.GetTaskRequest.newBuilder(); - builder.setId(taskQueryParams.id()); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_METHOD, builder, agentCard, context); - try { - StringBuilder url = new StringBuilder(Utils.buildBaseUrl(agentInterface, taskQueryParams.tenant())); - if (taskQueryParams.historyLength() != null && taskQueryParams.historyLength() > 0) { - url.append(String.format("/tasks/%1s?historyLength=%2d", taskQueryParams.id(), taskQueryParams.historyLength())); - } else { - url.append(String.format("/tasks/%1s", taskQueryParams.id())); - } - A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url.toString()); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - A2AHttpResponse response = getBuilder.get(); - if (!response.success()) { - throw RestErrorMapper.mapRestError(response); - } - String httpResponseBody = response.body(); - io.a2a.grpc.Task.Builder responseBuilder = io.a2a.grpc.Task.newBuilder(); - JsonFormat.parser().merge(httpResponseBody, responseBuilder); - return ProtoUtils.FromProto.task(responseBuilder); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException e) { - throw new A2AClientException("Failed to get task: " + e, e); - } - } - - @Override - public Task cancelTask(TaskIdParams taskIdParams, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("taskIdParams", taskIdParams); - io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(); - builder.setId(taskIdParams.id()); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(CANCEL_TASK_METHOD, builder, agentCard, context); - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, taskIdParams.tenant()) + String.format("/tasks/%1s:cancel", taskIdParams.id()), payloadAndHeaders); - io.a2a.grpc.Task.Builder responseBuilder = io.a2a.grpc.Task.newBuilder(); - JsonFormat.parser().merge(httpResponseBody, responseBuilder); - return ProtoUtils.FromProto.task(responseBuilder); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to cancel task: " + e, e); - } - } - - @Override - public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - io.a2a.grpc.ListTasksRequest.Builder builder = io.a2a.grpc.ListTasksRequest.newBuilder(); - if (request.contextId() != null) { - builder.setContextId(request.contextId()); - } - if (request.status() != null) { - builder.setStatus(ProtoUtils.ToProto.taskState(request.status())); - } - if (request.pageSize() != null) { - builder.setPageSize(request.pageSize()); - } - if (request.pageToken() != null) { - builder.setPageToken(request.pageToken()); - } - if (request.historyLength() != null) { - builder.setHistoryLength(request.historyLength()); - } - if (request.tenant() != null) { - builder.setTenant(request.tenant()); - } - if (request.includeArtifacts() != null && request.includeArtifacts()) { - builder.setIncludeArtifacts(true); - } - - PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_METHOD, builder, agentCard, context); - - try { - // Build query string - StringBuilder urlBuilder = new StringBuilder(Utils.buildBaseUrl(agentInterface, request.tenant())); - urlBuilder.append("/tasks"); - String queryParams = buildListTasksQueryString(request); - if (!queryParams.isEmpty()) { - urlBuilder.append("?").append(queryParams); - } - - A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(urlBuilder.toString()); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - A2AHttpResponse response = getBuilder.get(); - if (!response.success()) { - throw RestErrorMapper.mapRestError(response); - } - String httpResponseBody = response.body(); - io.a2a.grpc.ListTasksResponse.Builder responseBuilder = io.a2a.grpc.ListTasksResponse.newBuilder(); - JsonFormat.parser().merge(httpResponseBody, responseBuilder); - - return new ListTasksResult( - responseBuilder.getTasksList().stream() - .map(ProtoUtils.FromProto::task) - .toList(), - responseBuilder.getTotalSize(), - responseBuilder.getTasksCount(), - responseBuilder.getNextPageToken().isEmpty() ? null : responseBuilder.getNextPageToken() - ); - } catch (IOException | InterruptedException e) { - throw new A2AClientException("Failed to list tasks: " + e, e); - } - } - - - private String buildListTasksQueryString(ListTasksParams request) { - java.util.List queryParts = new java.util.ArrayList<>(); - if (request.contextId() != null) { - queryParts.add("contextId=" + URLEncoder.encode(request.contextId(), StandardCharsets.UTF_8)); - } - if (request.status() != null) { - queryParts.add("status=" + request.status()); - } - if (request.pageSize() != null) { - queryParts.add("pageSize=" + request.pageSize()); - } - if (request.pageToken() != null) { - queryParts.add("pageToken=" + URLEncoder.encode(request.pageToken(), StandardCharsets.UTF_8)); - } - if (request.historyLength() != null) { - queryParts.add("historyLength=" + request.historyLength()); - } - if (request.includeArtifacts() != null && request.includeArtifacts()) { - queryParts.add("includeArtifacts=true"); - } - return String.join("&", queryParts); - } - - @Override - public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder - = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); - builder.setConfig(ProtoUtils.ToProto.taskPushNotificationConfig(request).getPushNotificationConfig()) - .setTaskId(request.taskId()); - if (request.config().id() != null) { - builder.setConfigId(request.config().id()); - } - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); - try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs", request.taskId()), payloadAndHeaders); - io.a2a.grpc.TaskPushNotificationConfig.Builder responseBuilder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); - JsonFormat.parser().merge(httpResponseBody, responseBuilder); - return ProtoUtils.FromProto.taskPushNotificationConfig(responseBuilder); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to set task push notification config: " + e, e); - } - } - - @Override - public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder - = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); - StringBuilder url = new StringBuilder(Utils.buildBaseUrl(agentInterface, request.tenant())); - String configId = request.id(); - if (configId != null && !configId.isEmpty()) { - builder.setId(configId).setTaskId(request.taskId()); - url.append(String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.taskId(), configId)); - } else { - // Use trailing slash to distinguish GET from LIST - builder.setTaskId(request.taskId()); - url.append(String.format("/tasks/%1s/pushNotificationConfigs/", request.taskId())); - } - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, - agentCard, context); - try { - A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url.toString()); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - A2AHttpResponse response = getBuilder.get(); - if (!response.success()) { - throw RestErrorMapper.mapRestError(response); - } - String httpResponseBody = response.body(); - io.a2a.grpc.TaskPushNotificationConfig.Builder responseBuilder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); - JsonFormat.parser().merge(httpResponseBody, responseBuilder); - return ProtoUtils.FromProto.taskPushNotificationConfig(responseBuilder); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException e) { - throw new A2AClientException("Failed to get push notifications: " + e, e); - } - } - - @Override - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder builder - = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder(); - builder.setTaskId(request.id()); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, - agentCard, context); - try { - String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs", request.id()); - A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - A2AHttpResponse response = getBuilder.get(); - if (!response.success()) { - throw RestErrorMapper.mapRestError(response); - } - String httpResponseBody = response.body(); - io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder responseBuilder = io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder(); - JsonFormat.parser().merge(httpResponseBody, responseBuilder); - return ProtoUtils.FromProto.listTaskPushNotificationConfigResult(responseBuilder); - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException e) { - throw new A2AClientException("Failed to list push notifications: " + e, e); - } - } - - @Override - public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, - agentCard, context); - try { - String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.taskId(), request.id()); - A2AHttpClient.DeleteBuilder deleteBuilder = httpClient.createDelete().url(url); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - deleteBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - A2AHttpResponse response = deleteBuilder.delete(); - if (!response.success()) { - throw RestErrorMapper.mapRestError(response); - } - } catch (A2AClientException e) { - throw e; - } catch (IOException | InterruptedException e) { - throw new A2AClientException("Failed to delete push notification config: " + e, e); - } - } - - @Override - public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - checkNotNullParam("request", request); - io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); - builder.setId(request.id()); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, builder, - agentCard, context); - AtomicReference> ref = new AtomicReference<>(); - SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); - try { - String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s:subscribe", request.id()); - A2AHttpClient.PostBuilder postBuilder = createPostBuilder(url, payloadAndHeaders); - ref.set(postBuilder.postAsyncSSE( - msg -> sseEventListener.onMessage(msg, ref.get()), - throwable -> sseEventListener.onError(throwable, ref.get()), - () -> { - // We don't need to do anything special on completion - })); - } catch (IOException e) { - throw new A2AClientException("Failed to send streaming message request: " + e, e); - } catch (InterruptedException e) { - throw new A2AClientException("Send streaming message request timed out: " + e, e); - } catch (JsonProcessingException e) { - throw new A2AClientException("Failed to process JSON for streaming message request: " + e, e); - } - } - - @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - try { - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, null, agentCard, context); - String url = Utils.buildBaseUrl(agentInterface, "") + "/extendedAgentCard"; - A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - getBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - A2AHttpResponse response = getBuilder.get(); - if (!response.success()) { - throw RestErrorMapper.mapRestError(response); - } - String httpResponseBody = response.body(); - return JsonUtil.fromJson(httpResponseBody, AgentCard.class); - } catch (IOException | InterruptedException | JsonProcessingException e) { - throw new A2AClientException("Failed to get authenticated extended agent card: " + e, e); - } catch (A2AClientError e) { - throw new A2AClientException("Failed to get agent card: " + e, e); - } - } - - @Override - public void close() { - // no-op - } - - private PayloadAndHeaders applyInterceptors(String methodName, @Nullable MessageOrBuilder payload, - AgentCard agentCard, @Nullable ClientCallContext clientCallContext) { - PayloadAndHeaders payloadAndHeaders = new PayloadAndHeaders(payload, getHttpHeaders(clientCallContext)); - if (interceptors != null && !interceptors.isEmpty()) { - for (ClientCallInterceptor interceptor : interceptors) { - payloadAndHeaders = interceptor.intercept(methodName, payloadAndHeaders.getPayload(), - payloadAndHeaders.getHeaders(), agentCard, clientCallContext); - } - } - return payloadAndHeaders; - } - - private String sendPostRequest(String url, PayloadAndHeaders payloadAndHeaders) throws IOException, InterruptedException, JsonProcessingException { - A2AHttpClient.PostBuilder builder = createPostBuilder(url, payloadAndHeaders); - A2AHttpResponse response = builder.post(); - if (!response.success()) { - log.fine("Error on POST processing " + JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); - throw RestErrorMapper.mapRestError(response); - } - return response.body(); - } - - private A2AHttpClient.PostBuilder createPostBuilder(String url, PayloadAndHeaders payloadAndHeaders) throws JsonProcessingException, InvalidProtocolBufferException { - log.fine(JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); - A2AHttpClient.PostBuilder postBuilder = httpClient.createPost() - .url(url) - .addHeader("Content-Type", "application/json") - .body(JsonFormat.printer().print((MessageOrBuilder) payloadAndHeaders.getPayload())); - - if (payloadAndHeaders.getHeaders() != null) { - for (Map.Entry entry : payloadAndHeaders.getHeaders().entrySet()) { - postBuilder.addHeader(entry.getKey(), entry.getValue()); - } - } - return postBuilder; - } - - private Map getHttpHeaders(@Nullable ClientCallContext context) { - return context != null ? context.getHeaders() : Collections.emptyMap(); - } -} diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java deleted file mode 100644 index e78c67271..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfig.java +++ /dev/null @@ -1,84 +0,0 @@ -package io.a2a.client.transport.rest; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.transport.spi.ClientTransportConfig; -import org.jspecify.annotations.Nullable; - -/** - * Configuration for the REST transport protocol. - *

- * This configuration class allows customization of the HTTP client used for RESTful - * communication with A2A agents. If no HTTP client is specified, the default JDK-based - * implementation is used. - *

- * Basic usage: - *

{@code
- * // Use default HTTP client
- * RestTransportConfig config = new RestTransportConfigBuilder()
- *     .build();
- *
- * Client client = Client.builder(agentCard)
- *     .withTransport(RestTransport.class, config)
- *     .build();
- * }
- *

- * Custom HTTP client: - *

{@code
- * // Custom HTTP client with timeouts
- * A2AHttpClient customClient = new CustomHttpClient()
- *     .withConnectTimeout(Duration.ofSeconds(10))
- *     .withReadTimeout(Duration.ofSeconds(30));
- *
- * RestTransportConfig config = new RestTransportConfigBuilder()
- *     .httpClient(customClient)
- *     .build();
- * }
- *

- * With interceptors: - *

{@code
- * RestTransportConfig config = new RestTransportConfigBuilder()
- *     .httpClient(customClient)
- *     .addInterceptor(new LoggingInterceptor())
- *     .addInterceptor(new AuthInterceptor("Bearer token"))
- *     .build();
- * }
- * - * @see RestTransportConfigBuilder - * @see RestTransport - * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient - */ -public class RestTransportConfig extends ClientTransportConfig { - - private final @Nullable A2AHttpClient httpClient; - - /** - * Create a REST transport configuration with the default HTTP client. - *

- * The default JDK-based HTTP client will be used. Consider using - * {@link RestTransportConfigBuilder} instead for a more fluent API. - */ - public RestTransportConfig() { - this.httpClient = null; - } - - /** - * Create a REST transport configuration with a custom HTTP client. - *

- * Consider using {@link RestTransportConfigBuilder} instead for a more fluent API. - * - * @param httpClient the HTTP client to use for REST requests - */ - public RestTransportConfig(A2AHttpClient httpClient) { - this.httpClient = httpClient; - } - - /** - * Get the configured HTTP client. - * - * @return the HTTP client, or {@code null} if using the default - */ - public @Nullable A2AHttpClient getHttpClient() { - return httpClient; - } -} \ No newline at end of file diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfigBuilder.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfigBuilder.java deleted file mode 100644 index 257836199..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportConfigBuilder.java +++ /dev/null @@ -1,120 +0,0 @@ -package io.a2a.client.transport.rest; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportConfigBuilder; -import org.jspecify.annotations.Nullable; - -/** - * Builder for creating {@link RestTransportConfig} instances. - *

- * This builder provides a fluent API for configuring the REST transport protocol. - * All configuration options are optional - if not specified, sensible defaults are used: - *

    - *
  • HTTP client: Auto-selected via {@link A2AHttpClientFactory} (prefers Vert.x, falls back to JDK)
  • - *
  • Interceptors: None
  • - *
- *

- * Basic usage: - *

{@code
- * // Minimal configuration (uses all defaults)
- * RestTransportConfig config = new RestTransportConfigBuilder()
- *     .build();
- *
- * Client client = Client.builder(agentCard)
- *     .withTransport(RestTransport.class, config)
- *     .build();
- * }
- *

- * Custom HTTP client: - *

{@code
- * // Configure custom HTTP client for connection pooling, timeouts, etc.
- * A2AHttpClient httpClient = new ApacheHttpClient()
- *     .withConnectionTimeout(Duration.ofSeconds(10))
- *     .withMaxConnections(50);
- *
- * RestTransportConfig config = new RestTransportConfigBuilder()
- *     .httpClient(httpClient)
- *     .build();
- * }
- *

- * With interceptors: - *

{@code
- * RestTransportConfig config = new RestTransportConfigBuilder()
- *     .addInterceptor(new LoggingInterceptor())
- *     .addInterceptor(new MetricsInterceptor())
- *     .addInterceptor(new RetryInterceptor(3))
- *     .build();
- * }
- *

- * Direct usage in ClientBuilder: - *

{@code
- * // Can pass builder directly to withTransport()
- * Client client = Client.builder(agentCard)
- *     .withTransport(RestTransport.class, new RestTransportConfigBuilder()
- *         .httpClient(customClient)
- *         .addInterceptor(loggingInterceptor))
- *     .build();
- * }
- * - * @see RestTransportConfig - * @see RestTransport - * @see A2AHttpClient - * @see io.a2a.client.http.JdkA2AHttpClient - */ -public class RestTransportConfigBuilder extends ClientTransportConfigBuilder { - - private @Nullable A2AHttpClient httpClient; - - /** - * Set the HTTP client to use for REST requests. - *

- * Custom HTTP clients can provide: - *

    - *
  • Connection pooling and reuse
  • - *
  • Custom timeout configuration
  • - *
  • SSL/TLS configuration
  • - *
  • Proxy support
  • - *
  • Custom header handling
  • - *
- *

- * If not specified, a client is auto-selected via {@link A2AHttpClientFactory}. - *

- * Example: - *

{@code
-     * A2AHttpClient client = new CustomHttpClient()
-     *     .withConnectTimeout(Duration.ofSeconds(5))
-     *     .withReadTimeout(Duration.ofSeconds(30))
-     *     .withConnectionPool(10, 50);
-     *
-     * builder.httpClient(client);
-     * }
- * - * @param httpClient the HTTP client to use - * @return this builder for method chaining - */ - public RestTransportConfigBuilder httpClient(A2AHttpClient httpClient) { - this.httpClient = httpClient; - return this; - } - - /** - * Build the REST transport configuration. - *

- * If no HTTP client was configured, one is auto-selected via {@link A2AHttpClientFactory}. - * Any configured interceptors are transferred to the configuration. - * - * @return the configured REST transport configuration - */ - @Override - public RestTransportConfig build() { - // No HTTP client provided, use factory to get best available implementation - if (httpClient == null) { - httpClient = A2AHttpClientFactory.create(); - } - - RestTransportConfig config = new RestTransportConfig(httpClient); - config.setInterceptors(this.interceptors); - return config; - } -} \ No newline at end of file diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportProvider.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportProvider.java deleted file mode 100644 index b6e6d7a47..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransportProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.a2a.client.transport.rest; - -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.transport.spi.ClientTransportProvider; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; - -public class RestTransportProvider implements ClientTransportProvider { - - @Override - public String getTransportProtocol() { - return TransportProtocol.HTTP_JSON.asString(); - } - - @Override - public RestTransport create(RestTransportConfig clientTransportConfig, AgentCard agentCard, AgentInterface agentInterface) throws A2AClientException { - RestTransportConfig transportConfig = clientTransportConfig; - if (transportConfig == null) { - transportConfig = new RestTransportConfig(A2AHttpClientFactory.create()); - } - return new RestTransport(transportConfig.getHttpClient(), agentCard, agentInterface, transportConfig.getInterceptors()); - } - - @Override - public Class getTransportProtocolClass() { - return RestTransport.class; - } -} diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/package-info.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/package-info.java deleted file mode 100644 index b7892c239..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.rest; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java deleted file mode 100644 index 2c9167b63..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/SSEEventListener.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.a2a.client.transport.rest.sse; - -import java.util.concurrent.Future; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.util.JsonFormat; -import io.a2a.client.transport.spi.sse.AbstractSSEEventListener; -import io.a2a.client.transport.rest.RestErrorMapper; -import io.a2a.grpc.StreamResponse; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.spec.StreamingEventKind; -import org.jspecify.annotations.Nullable; - -/** - * REST transport implementation of SSE event listener. - * Handles parsing of JSON-formatted protobuf messages from REST SSE streams. - */ -public class SSEEventListener extends AbstractSSEEventListener { - - private static final Logger log = Logger.getLogger(SSEEventListener.class.getName()); - - public SSEEventListener(Consumer eventHandler, - @Nullable Consumer errorHandler) { - super(eventHandler, errorHandler); - } - - @Override - public void onMessage(String message, @Nullable Future completableFuture) { - try { - log.fine("Streaming message received: " + message); - io.a2a.grpc.StreamResponse.Builder builder = io.a2a.grpc.StreamResponse.newBuilder(); - JsonFormat.parser().merge(message, builder); - parseAndHandleMessage(builder.build(), completableFuture); - } catch (InvalidProtocolBufferException e) { - if (getErrorHandler() != null) { - getErrorHandler().accept(RestErrorMapper.mapRestError(message, 500)); - } - } - } - - /** - * Parses a StreamResponse protobuf message and delegates to the base class for event handling. - * - * @param response The parsed StreamResponse - * @param future Optional future for controlling the SSE connection - */ - private void parseAndHandleMessage(StreamResponse response, @Nullable Future future) { - StreamingEventKind event; - switch (response.getPayloadCase()) { - case MESSAGE -> - event = ProtoUtils.FromProto.message(response.getMessage()); - case TASK -> - event = ProtoUtils.FromProto.task(response.getTask()); - case STATUS_UPDATE -> - event = ProtoUtils.FromProto.taskStatusUpdateEvent(response.getStatusUpdate()); - case ARTIFACT_UPDATE -> - event = ProtoUtils.FromProto.taskArtifactUpdateEvent(response.getArtifactUpdate()); - default -> { - log.warning("Invalid stream response " + response.getPayloadCase()); - if (getErrorHandler() != null) { - getErrorHandler().accept(new IllegalStateException("Invalid stream response from server: " + response.getPayloadCase())); - } - return; - } - } - - // Delegate to base class for common event handling and auto-close logic - handleEvent(event, future); - } - -} diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/package-info.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/package-info.java deleted file mode 100644 index e1bb6c3b2..000000000 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/sse/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.rest.sse; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/rest/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider b/client/transport/rest/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider deleted file mode 100644 index 894866aab..000000000 --- a/client/transport/rest/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.transport.rest.RestTransportProvider \ No newline at end of file diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java deleted file mode 100644 index 35ac4a9c5..000000000 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/JsonRestMessages.java +++ /dev/null @@ -1,399 +0,0 @@ -package io.a2a.client.transport.rest; - -/** - * Request and response messages used by the tests. These have been created following examples from - * the A2A sample messages. - */ -public class JsonRestMessages { - - static final String SEND_MESSAGE_TEST_REQUEST = """ - { - "message": - { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": { - } - } - }"""; - - static final String SEND_MESSAGE_TEST_RESPONSE = """ - { - "task": { - "id": "9b511af4-b27c-47fa-aecf-2a93c08a44f8", - "contextId": "context-1234", - "status": { - "state": "TASK_STATE_SUBMITTED" - }, - "history": [ - { - "messageId": "message-1234", - "contextId": "context-1234", - "taskId": "9b511af4-b27c-47fa-aecf-2a93c08a44f8", - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me a joke" - } - ], - "metadata": {} - } - ] - } - }"""; - - static final String CANCEL_TASK_TEST_REQUEST = """ - { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64" - }"""; - - static final String CANCEL_TASK_TEST_RESPONSE = """ - { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", - "status": { - "state": "TASK_STATE_CANCELED" - }, - "metadata": {} - }"""; - - static final String GET_TASK_TEST_RESPONSE = """ - { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", - "status": { - "state": "TASK_STATE_COMPLETED" - }, - "artifacts": [ - { - "artifactId": "artifact-1", - "parts": [ - { - "text": "Why did the chicken cross the road? To get to the other side!" - } - ] - } - ], - "history": [ - { - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me a joke" - }, - { - "url": "file:///path/to/file.txt", - "mediaType": "text/plain" - }, - { - "raw": "aGVsbG8=", - "mediaType": "text/plain" - } - ], - "messageId": "message-123" - } - ], - "metadata": {} - } - """; - - static final String AGENT_CARD = """ - { - "name": "GeoSpatial Route Planner Agent", - "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", - "supportedInterfaces": [ - {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "HTTP+JSON"} - ], - "provider": { - "organization": "Example Geo Services Inc.", - "url": "https://www.examplegeoservices.com" - }, - "iconUrl": "https://georoute-agent.example.com/icon.png", - "version": "1.2.0", - "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", - "capabilities": { - "streaming": true, - "pushNotifications": true - }, - "securitySchemes": { - "google": { - "type": "openIdConnect", - "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" - } - }, - "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], - "defaultInputModes": ["application/json", "text/plain"], - "defaultOutputModes": ["application/json", "image/png"], - "skills": [ - { - "id": "route-optimizer-traffic", - "name": "Traffic-Aware Route Optimizer", - "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", - "tags": ["maps", "routing", "navigation", "directions", "traffic"], - "examples": [ - "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" - ], - "inputModes": ["application/json", "text/plain"], - "outputModes": [ - "application/json", - "application/vnd.geo+json", - "text/html" - ] - }, - { - "id": "custom-map-generator", - "name": "Personalized Map Generator", - "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", - "tags": ["maps", "customization", "visualization", "cartography"], - "examples": [ - "Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." - ], - "inputModes": ["application/json"], - "outputModes": [ - "image/png", - "image/jpeg", - "application/json", - "text/html" - ] - } - ], - "supportsExtendedAgentCard": false, - "protocolVersion": "0.2.5" - }"""; - - static final String AGENT_CARD_SUPPORTS_EXTENDED = """ - { - "name": "GeoSpatial Route Planner Agent", - "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", - "supportedInterfaces": [ - {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "HTTP+JSON"} - ], - "provider": { - "organization": "Example Geo Services Inc.", - "url": "https://www.examplegeoservices.com" - }, - "iconUrl": "https://georoute-agent.example.com/icon.png", - "version": "1.2.0", - "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", - "capabilities": { - "streaming": true, - "pushNotifications": true - }, - "securitySchemes": { - "google": { - "type": "openIdConnect", - "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" - } - }, - "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], - "defaultInputModes": ["application/json", "text/plain"], - "defaultOutputModes": ["application/json", "image/png"], - "skills": [ - { - "id": "route-optimizer-traffic", - "name": "Traffic-Aware Route Optimizer", - "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", - "tags": ["maps", "routing", "navigation", "directions", "traffic"], - "examples": [ - "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" - ], - "inputModes": ["application/json", "text/plain"], - "outputModes": [ - "application/json", - "application/vnd.geo+json", - "text/html" - ] - }, - { - "id": "custom-map-generator", - "name": "Personalized Map Generator", - "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", - "tags": ["maps", "customization", "visualization", "cartography"], - "examples": [ - "Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." - ], - "inputModes": ["application/json"], - "outputModes": [ - "image/png", - "image/jpeg", - "application/json", - "text/html" - ] - } - ], - "supportsExtendedAgentCard": true, - "protocolVersion": "0.2.5" - }"""; - - static final String AUTHENTICATION_EXTENDED_AGENT_CARD = """ - { - "name": "GeoSpatial Route Planner Agent Extended", - "description": "Extended description", - "supportedInterfaces": [ - {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "HTTP+JSON"} - ], - "provider": { - "organization": "Example Geo Services Inc.", - "url": "https://www.examplegeoservices.com" - }, - "iconUrl": "https://georoute-agent.example.com/icon.png", - "version": "1.2.0", - "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", - "capabilities": { - "streaming": true, - "pushNotifications": true - }, - "securitySchemes": { - "google": { - "type": "openIdConnect", - "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" - } - }, - "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], - "defaultInputModes": ["application/json", "text/plain"], - "defaultOutputModes": ["application/json", "image/png"], - "skills": [ - { - "id": "route-optimizer-traffic", - "name": "Traffic-Aware Route Optimizer", - "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", - "tags": ["maps", "routing", "navigation", "directions", "traffic"], - "examples": [ - "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" - ], - "inputModes": ["application/json", "text/plain"], - "outputModes": [ - "application/json", - "application/vnd.geo+json", - "text/html" - ] - }, - { - "id": "custom-map-generator", - "name": "Personalized Map Generator", - "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", - "tags": ["maps", "customization", "visualization", "cartography"], - "examples": [ - "Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." - ], - "inputModes": ["application/json"], - "outputModes": [ - "image/png", - "image/jpeg", - "application/json", - "text/html" - ] - }, - { - "id": "skill-extended", - "name": "Extended Skill", - "description": "This is an extended skill.", - "tags": ["extended"] - } - ], - "supportsExtendedAgentCard": true, - "protocolVersion": "0.2.5" - }"""; - - static final String GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ - { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "10", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - }"""; - static final String LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ - { - "configs":[ - { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "10", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - }, - { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "5", - "pushNotificationConfig": { - "url": "https://test.com/callback" - } - } - ] - }"""; - - - static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST = """ - { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "configId": "default-config-id", - "config": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - }"""; - - static final String SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE = """ - { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "10", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - }"""; - - - public static final String SEND_MESSAGE_STREAMING_TEST_REQUEST = """ - { - "message": { - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me some jokes" - } - ], - "messageId": "message-1234", - "contextId": "context-1234" - }, - "configuration": { - "acceptedOutputModes": ["text"] - } - }"""; - static final String SEND_MESSAGE_STREAMING_TEST_RESPONSE - = "event: message\n" - + "data: {\"task\":{\"id\":\"2\",\"contextId\":\"context-1234\",\"status\":{\"state\":\"TASK_STATE_SUBMITTED\"},\"artifacts\":[{\"artifactId\":\"artifact-1\",\"name\":\"joke\",\"parts\":[{\"text\":\"Why did the chicken cross the road? To get to the other side!\"}]}],\"metadata\":{}}}\n\n"; - - static final String TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE - = "event: message\n" - + "data: {\"task\":{\"id\":\"2\",\"contextId\":\"context-1234\",\"status\":{\"state\":\"TASK_STATE_COMPLETED\"},\"artifacts\":[{\"artifactId\":\"artifact-1\",\"name\":\"joke\",\"parts\":[{\"text\":\"Why did the chicken cross the road? To get to the other side!\"}]}],\"metadata\":{}}}\n\n"; - public static final String TASK_RESUBSCRIPTION_TEST_REQUEST = """ - { - "jsonrpc": "2.0", - "method": "SubscribeToTask", - "params": { - "id": "task-1234" - } - }"""; -} diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java deleted file mode 100644 index 2f3ae18db..000000000 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/RestTransportTest.java +++ /dev/null @@ -1,611 +0,0 @@ -package io.a2a.client.transport.rest; - - -import static io.a2a.client.transport.rest.JsonRestMessages.CANCEL_TASK_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.CANCEL_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.GET_TASK_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_STREAMING_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_STREAMING_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.SEND_MESSAGE_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST; -import static io.a2a.client.transport.rest.JsonRestMessages.SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE; -import static io.a2a.client.transport.rest.JsonRestMessages.TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.Artifact; -import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.VersionNotSupportedError; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; -import org.mockserver.matchers.MatchType; -import org.mockserver.model.JsonBody; - -public class RestTransportTest { - - private static final Logger log = Logger.getLogger(RestTransportTest.class.getName()); - private ClientAndServer server; - private static final AgentCard CARD = AgentCard.builder() - .name("Hello World Agent") - .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList(new io.a2a.spec.AgentInterface("HTTP+JSON", "http://localhost:4001"))) - .version("1.0.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(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(); - - @BeforeEach - public void setUp() throws IOException { - server = new ClientAndServer(4001); - } - - @AfterEach - public void tearDown() { - server.stop(); - } - - public RestTransportTest() { - } - - /** - * Test of sendMessage method, of class JSONRestTransport. - */ - @Test - public void testSendMessage() throws Exception { - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("tell me a joke"))) - .contextId("context-1234") - .messageId("message-1234") - .taskId("") - .build(); - this.server.when( - request() - .withMethod("POST") - .withPath("/message:send") - .withBody(JsonBody.json(SEND_MESSAGE_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - ) - .respond( - response() - .withStatusCode(200) - .withBody(SEND_MESSAGE_TEST_RESPONSE) - ); - MessageSendParams messageSendParams = new MessageSendParams(message, null, null, ""); - ClientCallContext context = null; - - RestTransport instance = new RestTransport(CARD); - EventKind result = instance.sendMessage(messageSendParams, context); - assertEquals("task", result.kind()); - Task task = (Task) result; - assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", task.id()); - assertEquals("context-1234", task.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, task.status().state()); - assertNull(task.status().message()); - assertNull(task.metadata()); - assertEquals(true, task.artifacts().isEmpty()); - assertEquals(1, task.history().size()); - Message history = task.history().get(0); - assertEquals("message", history.kind()); - assertEquals(Message.Role.ROLE_USER, history.role()); - assertEquals("context-1234", history.contextId()); - assertEquals("message-1234", history.messageId()); - assertEquals("9b511af4-b27c-47fa-aecf-2a93c08a44f8", history.taskId()); - assertEquals(1, history.parts().size()); - assertTrue(history.parts().get(0) instanceof io.a2a.spec.TextPart); - assertEquals("tell me a joke", ((TextPart) history.parts().get(0)).text()); - assertNull(task.metadata()); - assertNull(history.referenceTaskIds()); - } - - /** - * Test of cancelTask method, of class JSONRestTransport. - */ - @Test - public void testCancelTask() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64:cancel") - .withBody(JsonBody.json(CANCEL_TASK_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - ) - .respond( - response() - .withStatusCode(200) - .withBody(CANCEL_TASK_TEST_RESPONSE) - ); - ClientCallContext context = null; - RestTransport instance = new RestTransport(CARD); - Task task = instance.cancelTask(new TaskIdParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), context); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); - assertNull(task.status().message()); - assertNotNull(task.metadata()); - assertTrue(task.metadata().isEmpty()); - } - - /** - * Test of getTask method, of class JSONRestTransport. - */ - @Test - public void testGetTask() throws Exception { - this.server.when( - request() - .withMethod("GET") - .withPath("/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64") - ) - .respond( - response() - .withStatusCode(200) - .withBody(GET_TASK_TEST_RESPONSE) - ); - ClientCallContext context = null; - TaskQueryParams request = new TaskQueryParams("de38c76d-d54c-436c-8b9f-4c2703648d64", 10); - RestTransport instance = new RestTransport(CARD); - Task task = instance.getTask(request, context); - assertEquals("de38c76d-d54c-436c-8b9f-4c2703648d64", task.id()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - assertNull(task.status().message()); - assertNotNull(task.metadata()); - assertTrue(task.metadata().isEmpty()); - assertEquals(false, task.artifacts().isEmpty()); - assertEquals(1, task.artifacts().size()); - Artifact artifact = task.artifacts().get(0); - assertEquals("artifact-1", artifact.artifactId()); - assertNull(artifact.name()); - assertEquals(false, artifact.parts().isEmpty()); - assertTrue(artifact.parts().get(0) instanceof io.a2a.spec.TextPart); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) artifact.parts().get(0)).text()); - assertEquals(1, task.history().size()); - Message history = task.history().get(0); - assertEquals("message", history.kind()); - assertEquals(Message.Role.ROLE_USER, history.role()); - assertEquals("message-123", history.messageId()); - assertEquals(3, history.parts().size()); - assertTrue(history.parts().get(0) instanceof io.a2a.spec.TextPart); - assertEquals("tell me a joke", ((TextPart) history.parts().get(0)).text()); - assertTrue(history.parts().get(1) instanceof FilePart); - FilePart part = (FilePart) history.parts().get(1); - assertEquals("text/plain", part.file().mimeType()); - assertEquals("file:///path/to/file.txt", ((FileWithUri) part.file()).uri()); - part = (FilePart) history.parts().get(2); - assertTrue(part instanceof FilePart); - assertEquals("text/plain", part.file().mimeType()); - assertEquals("aGVsbG8=", ((FileWithBytes) part.file()).bytes()); - assertNull(history.metadata()); - assertNull(history.referenceTaskIds()); - } - - /** - * Test of sendMessageStreaming method, of class JSONRestTransport. - */ - @Test - public void testSendMessageStreaming() throws Exception { - this.server.when( - request() - .withMethod("POST") - .withPath("/message:stream") - .withBody(JsonBody.json(SEND_MESSAGE_STREAMING_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - ) - .respond( - response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody(SEND_MESSAGE_STREAMING_TEST_RESPONSE) - ); - - RestTransport client = new RestTransport(CARD); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("tell me some jokes"))) - .contextId("context-1234") - .messageId("message-1234") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(false) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - AtomicReference receivedEvent = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - Consumer eventHandler = event -> { - receivedEvent.set(event); - latch.countDown(); - }; - Consumer errorHandler = error -> { - }; - client.sendMessageStreaming(params, eventHandler, errorHandler, null); - - boolean eventReceived = latch.await(10, TimeUnit.SECONDS); - assertTrue(eventReceived); - assertNotNull(receivedEvent.get()); - assertEquals("task", receivedEvent.get().kind()); - Task task = (Task) receivedEvent.get(); - assertEquals("2", task.id()); - } - - /** - * Test of CreateTaskPushNotificationConfiguration method, of class JSONRestTransport. - */ - @Test - public void testCreateTaskPushNotificationConfiguration() throws Exception { - log.info("Testing CreateTaskPushNotificationConfiguration"); - this.server.when( - request() - .withMethod("POST") - .withPath("/tenant/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs") - .withBody(JsonBody.json(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_REQUEST, MatchType.ONLY_MATCHING_FIELDS)) - ) - .respond( - response() - .withStatusCode(200) - .withBody(SET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) - ); - RestTransport client = new RestTransport(CARD); - TaskPushNotificationConfig pushedConfig = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("default-config-id") - .url("https://example.com/callback") - .authentication( - new AuthenticationInfo("jwt", null)) - .build(), "tenant"); - TaskPushNotificationConfig taskPushNotificationConfig = client.createTaskPushNotificationConfiguration(pushedConfig, null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertEquals("jwt", authenticationInfo.scheme()); - } - - /** - * Test of getTaskPushNotificationConfiguration method, of class JSONRestTransport. - */ - @Test - public void testGetTaskPushNotificationConfiguration() throws Exception { - this.server.when( - request() - .withMethod("GET") - .withPath("/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10") - ) - .respond( - response() - .withStatusCode(200) - .withBody(GET_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) - ); - - RestTransport client = new RestTransport(CARD); - TaskPushNotificationConfig taskPushNotificationConfig = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64", "10"), null); - PushNotificationConfig pushNotificationConfig = taskPushNotificationConfig.config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertEquals("jwt", authenticationInfo.scheme()); - } - - /** - * Test of listTaskPushNotificationConfigurations method, of class JSONRestTransport. - */ - @Test - public void testListTaskPushNotificationConfigurations() throws Exception { - this.server.when( - request() - .withMethod("GET") - .withPath("/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs") - ) - .respond( - response() - .withStatusCode(200) - .withBody(LIST_TASK_PUSH_NOTIFICATION_CONFIG_TEST_RESPONSE) - ); - - RestTransport client = new RestTransport(CARD); - ListTaskPushNotificationConfigResult result = client.listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64"), null); - assertEquals(2, result.configs().size()); - PushNotificationConfig pushNotificationConfig = result.configs().get(0).config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://example.com/callback", pushNotificationConfig.url()); - assertEquals("10", pushNotificationConfig.id()); - AuthenticationInfo authenticationInfo = pushNotificationConfig.authentication(); - assertEquals("jwt", authenticationInfo.scheme()); - assertEquals("", authenticationInfo.credentials()); - pushNotificationConfig = result.configs().get(1).config(); - assertNotNull(pushNotificationConfig); - assertEquals("https://test.com/callback", pushNotificationConfig.url()); - assertEquals("5", pushNotificationConfig.id()); - authenticationInfo = pushNotificationConfig.authentication(); - assertNull(authenticationInfo); - } - - /** - * Test of deleteTaskPushNotificationConfigurations method, of class JSONRestTransport. - */ - @Test - public void testDeleteTaskPushNotificationConfigurations() throws Exception { - log.info("Testing deleteTaskPushNotificationConfigurations"); - this.server.when( - request() - .withMethod("DELETE") - .withPath("/tasks/de38c76d-d54c-436c-8b9f-4c2703648d64/pushNotificationConfigs/10") - ) - .respond( - response() - .withStatusCode(200) - ); - ClientCallContext context = null; - RestTransport instance = new RestTransport(CARD); - instance.deleteTaskPushNotificationConfigurations(new DeleteTaskPushNotificationConfigParams("de38c76d-d54c-436c-8b9f-4c2703648d64", "10"), context); - } - - /** - * Test of subscribe method, of class JSONRestTransport. - */ - @Test - public void testSubscribe() throws Exception { - log.info("Testing subscribeToTask"); - - this.server.when( - request() - .withMethod("POST") - .withPath("/tasks/task-1234:subscribe") - ) - .respond( - response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody(TASK_RESUBSCRIPTION_REQUEST_TEST_RESPONSE) - ); - - RestTransport client = new RestTransport(CARD); - TaskIdParams taskIdParams = new TaskIdParams("task-1234"); - - AtomicReference receivedEvent = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - Consumer eventHandler = event -> { - receivedEvent.set(event); - latch.countDown(); - }; - Consumer errorHandler = error -> {}; - client.subscribeToTask(taskIdParams, eventHandler, errorHandler, null); - - boolean eventReceived = latch.await(10, TimeUnit.SECONDS); - assertTrue(eventReceived); - - StreamingEventKind eventKind = receivedEvent.get();; - assertNotNull(eventKind); - assertInstanceOf(Task.class, eventKind); - Task task = (Task) eventKind; - assertEquals("2", task.id()); - assertEquals("context-1234", task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - List artifacts = task.artifacts(); - assertEquals(1, artifacts.size()); - Artifact artifact = artifacts.get(0); - assertEquals("artifact-1", artifact.artifactId()); - assertEquals("joke", artifact.name()); - Part part = artifact.parts().get(0); - assertTrue(part instanceof io.a2a.spec.TextPart); - assertEquals("Why did the chicken cross the road? To get to the other side!", ((TextPart) part).text()); - } - - /** - * Test that ExtensionSupportRequiredError is properly unmarshalled from REST error response. - */ - @Test - public void testExtensionSupportRequiredErrorUnmarshalling() throws Exception { - log.info("Testing ExtensionSupportRequiredError unmarshalling"); - - // Mock server returns HTTP 400 with ExtensionSupportRequiredError - String errorResponseBody = """ - { - "error": "io.a2a.spec.ExtensionSupportRequiredError", - "message": "Extension required: https://example.com/test-extension" - } - """; - - this.server.when( - request() - .withMethod("POST") - .withPath("/message:send") - ) - .respond( - response() - .withStatusCode(400) - .withHeader("Content-Type", "application/json") - .withBody(errorResponseBody) - ); - - RestTransport client = new RestTransport(CARD); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("test message"))) - .contextId("context-test") - .messageId("message-test") - .build(); - MessageSendParams params = new MessageSendParams(message, null, null, ""); - - // Should throw A2AClientException with ExtensionSupportRequiredError as cause - try { - client.sendMessage(params, null); - org.junit.jupiter.api.Assertions.fail("Expected A2AClientException to be thrown"); - } catch (A2AClientException e) { - // Verify the cause is ExtensionSupportRequiredError - assertInstanceOf(ExtensionSupportRequiredError.class, e.getCause()); - ExtensionSupportRequiredError extensionError = (ExtensionSupportRequiredError) e.getCause(); - assertTrue(extensionError.getMessage().contains("https://example.com/test-extension")); - } - } - - /** - * Test that VersionNotSupportedError is properly unmarshalled from REST error response. - */ - @Test - public void testVersionNotSupportedErrorUnmarshalling() throws Exception { - log.info("Testing VersionNotSupportedError unmarshalling"); - - // Mock server returns HTTP 501 with VersionNotSupportedError - String errorResponseBody = """ - { - "error": "io.a2a.spec.VersionNotSupportedError", - "message": "Protocol version 2.0 is not supported. This agent supports version 1.0" - } - """; - - this.server.when( - request() - .withMethod("POST") - .withPath("/message:send") - ) - .respond( - response() - .withStatusCode(501) - .withHeader("Content-Type", "application/json") - .withBody(errorResponseBody) - ); - - RestTransport client = new RestTransport(CARD); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("test message"))) - .contextId("context-test") - .messageId("message-test") - .build(); - MessageSendParams params = new MessageSendParams(message, null, null, ""); - - // Should throw A2AClientException with VersionNotSupportedError as cause - try { - client.sendMessage(params, null); - org.junit.jupiter.api.Assertions.fail("Expected A2AClientException to be thrown"); - } catch (A2AClientException e) { - // Verify the cause is VersionNotSupportedError - assertInstanceOf(VersionNotSupportedError.class, e.getCause()); - VersionNotSupportedError versionError = (VersionNotSupportedError) e.getCause(); - assertTrue(versionError.getMessage().contains("2.0")); - assertTrue(versionError.getMessage().contains("1.0")); - } - } - - /** - * Test that VersionNotSupportedError is properly handled in streaming responses. - */ - @Test - public void testVersionNotSupportedErrorUnmarshallingStreaming() throws Exception { - log.info("Testing VersionNotSupportedError unmarshalling in streaming"); - - // Mock server returns HTTP 200 with error event in SSE stream - String streamResponseBody = """ - data: {"kind":"error","error":"io.a2a.spec.VersionNotSupportedError","message":"Protocol version 2.0 is not supported. This agent supports version 1.0"} - - """; - - this.server.when( - request() - .withMethod("POST") - .withPath("/message:stream") - ) - .respond( - response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody(streamResponseBody) - ); - - RestTransport client = new RestTransport(CARD); - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("test message"))) - .contextId("context-test") - .messageId("message-test") - .build(); - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .blocking(false) - .build(); - MessageSendParams params = MessageSendParams.builder() - .message(message) - .configuration(configuration) - .build(); - - AtomicReference receivedError = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - Consumer eventHandler = event -> { - // Should not receive events, only error - }; - Consumer errorHandler = error -> { - receivedError.set(error); - latch.countDown(); - }; - client.sendMessageStreaming(params, eventHandler, errorHandler, null); - - boolean errorReceived = latch.await(10, TimeUnit.SECONDS); - assertTrue(errorReceived); - assertNotNull(receivedError.get()); - assertInstanceOf(A2AClientException.class, receivedError.get()); - A2AClientException clientException = (A2AClientException) receivedError.get(); - assertInstanceOf(VersionNotSupportedError.class, clientException.getCause()); - VersionNotSupportedError versionError = (VersionNotSupportedError) clientException.getCause(); - assertTrue(versionError.getMessage().contains("2.0")); - assertTrue(versionError.getMessage().contains("1.0")); - } -} diff --git a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java b/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java deleted file mode 100644 index d208f25c3..000000000 --- a/client/transport/rest/src/test/java/io/a2a/client/transport/rest/sse/SSEEventListenerTest.java +++ /dev/null @@ -1,342 +0,0 @@ -package io.a2a.client.transport.rest.sse; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; - -/** - * Tests for REST transport SSEEventListener. - * Tests JSON parsing of protobuf messages and event handling. - */ -public class SSEEventListenerTest { - - /** - * Mock Future implementation that captures cancel calls. - */ - private static class CancelCapturingFuture implements Future { - private boolean cancelHandlerCalled = false; - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - cancelHandlerCalled = true; - return true; - } - - @Override - public boolean isCancelled() { - return cancelHandlerCalled; - } - - @Override - public boolean isDone() { - return false; - } - - @Override - public Void get() { - return null; - } - - @Override - public Void get(long timeout, TimeUnit unit) { - return null; - } - - public boolean wasCancelled() { - return cancelHandlerCalled; - } - } - - @Test - public void testOnMessageWithTaskResult() { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // JSON format from REST SSE stream (protobuf as JSON) - String jsonMessage = """ - { - "task": { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_WORKING" - } - } - } - """; - - // Call the onMessage method - listener.onMessage(jsonMessage, null); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof Task); - Task task = (Task) receivedEvent.get(); - assertEquals("task-123", task.id()); - assertEquals("context-456", task.contextId()); - assertEquals(TaskState.TASK_STATE_WORKING, task.status().state()); - } - - @Test - public void testOnMessageWithMessageResult() { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // JSON format from REST SSE stream - String jsonMessage = """ - { - "message": { - "role": "ROLE_AGENT", - "messageId": "msg-123", - "contextId": "context-456", - "parts": [ - { - "text": "Hello, world!" - } - ] - } - } - """; - - // Call onMessage method - listener.onMessage(jsonMessage, null); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof Message); - Message message = (Message) receivedEvent.get(); - assertEquals(Message.Role.ROLE_AGENT, message.role()); - assertEquals("msg-123", message.messageId()); - assertEquals("context-456", message.contextId()); - assertEquals(1, message.parts().size()); - assertTrue(message.parts().get(0) instanceof TextPart); - assertEquals("Hello, world!", ((TextPart) message.parts().get(0)).text()); - } - - @Test - public void testOnMessageWithStatusUpdateEvent() { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // JSON format from REST SSE stream - String jsonMessage = """ - { - "statusUpdate": { - "taskId": "1", - "contextId": "2", - "status": { - "state": "TASK_STATE_SUBMITTED" - } - } - } - """; - - // Call onMessage method - listener.onMessage(jsonMessage, null); - - // Verify the event was processed correctly - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); - TaskStatusUpdateEvent taskStatusUpdateEvent = (TaskStatusUpdateEvent) receivedEvent.get(); - assertEquals("1", taskStatusUpdateEvent.taskId()); - assertEquals("2", taskStatusUpdateEvent.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, taskStatusUpdateEvent.status().state()); - assertEquals(false, taskStatusUpdateEvent.isFinal()); - } - - @Test - public void testOnMessageWithFinalStatusUpdateEventCancels() { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // JSON format from REST SSE stream with final status - String jsonMessage = """ - { - "statusUpdate": { - "taskId": "1", - "contextId": "2", - "status": { - "state": "TASK_STATE_COMPLETED" - } - } - } - """; - - // Call onMessage with a cancellable future - CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(jsonMessage, future); - - // Verify the event was received and processed - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof TaskStatusUpdateEvent); - TaskStatusUpdateEvent received = (TaskStatusUpdateEvent) receivedEvent.get(); - assertTrue(received.isFinal()); - assertEquals(TaskState.TASK_STATE_COMPLETED, received.status().state()); - - // Verify the future was cancelled (auto-close on final event) - assertTrue(future.wasCancelled()); - } - - @Test - public void testOnMessageWithCompletedTaskCancels() { - // Set up event handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - error -> {} - ); - - // JSON format from REST SSE stream with completed task - String jsonMessage = """ - { - "task": { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_COMPLETED" - } - } - } - """; - - // Call onMessage with a cancellable future - CancelCapturingFuture future = new CancelCapturingFuture(); - listener.onMessage(jsonMessage, future); - - // Verify the event was received - assertNotNull(receivedEvent.get()); - assertTrue(receivedEvent.get() instanceof Task); - Task task = (Task) receivedEvent.get(); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - - // Verify the future was cancelled (auto-close on final task state) - assertTrue(future.wasCancelled()); - } - - @Test - public void testOnMessageWithInvalidJsonCallsErrorHandler() { - // Set up error handler - AtomicReference receivedError = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> {}, - error -> receivedError.set(error) - ); - - // Invalid JSON message - String invalidJson = "{ invalid json }"; - - // Call onMessage - listener.onMessage(invalidJson, null); - - // Verify error handler was called - assertNotNull(receivedError.get()); - } - - @Test - public void testOnMessageWithInvalidPayloadCaseCallsErrorHandler() { - // Set up error handler - AtomicReference receivedError = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> {}, - error -> receivedError.set(error) - ); - - // JSON with no recognized payload type (empty object) - String jsonMessage = "{}"; - - // Call onMessage - listener.onMessage(jsonMessage, null); - - // Verify error handler was called - assertNotNull(receivedError.get()); - assertTrue(receivedError.get() instanceof IllegalStateException); - assertTrue(receivedError.get().getMessage().contains("Invalid stream response")); - } - - @Test - public void testOnErrorCallsErrorHandler() { - // Set up error handler - AtomicReference receivedError = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> {}, - error -> receivedError.set(error) - ); - - // Create a test error - IllegalStateException testError = new IllegalStateException("Test error"); - - // Call onError - listener.onError(testError, null); - - // Verify error handler was called - assertNotNull(receivedError.get()); - assertEquals(testError, receivedError.get()); - } - - @Test - public void testOnErrorCancelsFuture() { - // Set up error handler - AtomicBoolean errorHandlerCalled = new AtomicBoolean(false); - SSEEventListener listener = new SSEEventListener( - event -> {}, - error -> errorHandlerCalled.set(true) - ); - - // Create a cancel-capturing future - CancelCapturingFuture future = new CancelCapturingFuture(); - - // Call onError with a future - listener.onError(new RuntimeException("Test error"), future); - - // Verify both error handler was called and future was cancelled - assertTrue(errorHandlerCalled.get()); - assertTrue(future.wasCancelled()); - } - - @Test - public void testOnMessageWithNullErrorHandler() { - // Set up with null error handler - AtomicReference receivedEvent = new AtomicReference<>(); - SSEEventListener listener = new SSEEventListener( - event -> receivedEvent.set(event), - null // Null error handler - ); - - // Invalid JSON message - String invalidJson = "{ invalid json }"; - - // Call onMessage - should not throw even with null error handler - listener.onMessage(invalidJson, null); - - // No exception thrown means test passes - } -} diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml deleted file mode 100644 index 393d044d6..000000000 --- a/client/transport/spi/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../../pom.xml - - a2a-java-sdk-client-transport-spi - jar - - Java SDK A2A Client Transport: SPI - Java SDK for the Agent2Agent Protocol (A2A) - Client Transport SPI - - - - io.github.a2asdk - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-params - test - - - - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java deleted file mode 100644 index 82fe40996..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java +++ /dev/null @@ -1,153 +0,0 @@ -package io.a2a.client.transport.spi; - -import java.util.function.Consumer; - -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import org.jspecify.annotations.Nullable; - -/** - * Interface for a client transport. - */ -public interface ClientTransport { - - /** - * Send a non-streaming message request to the agent. - * - * @param request the message send parameters - * @param context optional client call context for the request (may be {@code null}) - * @return the response, either a Task or Message - * @throws A2AClientException if sending the message fails for any reason - */ - EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) - throws A2AClientException; - - /** - * Send a streaming message request to the agent and receive responses as they arrive. - * - * @param request the message send parameters - * @param eventConsumer consumer that will receive streaming events as they arrive - * @param errorConsumer consumer that will be called if an error occurs during streaming - * @param context optional client call context for the request (may be {@code null}) - * @throws A2AClientException if setting up the streaming connection fails - */ - void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the current state and history of a specific task. - * - * @param request the task query parameters specifying which task to retrieve - * @param context optional client call context for the request (may be {@code null}) - * @return the task - * @throws A2AClientException if retrieving the task fails for any reason - */ - Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Request the agent to cancel a specific task. - * - * @param request the task ID parameters specifying which task to cancel - * @param context optional client call context for the request (may be {@code null}) - * @return the cancelled task - * @throws A2AClientException if cancelling the task fails for any reason - */ - Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * List tasks with optional filtering and pagination. - * - * @param request the list tasks parameters including filters and pagination - * @param context optional client call context for the request (may be {@code null}) - * @return the list tasks result containing tasks and pagination information - * @throws A2AClientException if listing tasks fails for any reason - */ - ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Create or update the push notification configuration for a specific task. - * - * @param request the push notification configuration to set for the task - * @param context optional client call context for the request (may be {@code null}) - * @return the configured TaskPushNotificationConfig - * @throws A2AClientException if creating or updating the task push notification configuration fails for any reason - */ - TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the push notification configuration for a specific task. - * - * @param request the parameters specifying which task's notification config to retrieve - * @param context optional client call context for the request (may be {@code null}) - * @return the task push notification config - * @throws A2AClientException if getting the task push notification config fails for any reason - */ - TaskPushNotificationConfig getTaskPushNotificationConfiguration( - GetTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the list of push notification configurations for a specific task with pagination support. - * - * @param request the parameters specifying which task's notification configs to retrieve - * @param context optional client call context for the request (may be {@code null}) - * @return the result containing the list of task push notification configs and pagination information - * @throws A2AClientException if getting the task push notification configs fails for any reason - */ - ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations( - ListTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Delete the list of push notification configurations for a specific task. - * - * @param request the parameters specifying which task's notification configs to delete - * @param context optional client call context for the request (may be {@code null}) - * @throws A2AClientException if deleting the task push notification configs fails for any reason - */ - void deleteTaskPushNotificationConfigurations( - DeleteTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Reconnect to get task updates for an existing task. - * - * @param request the task ID parameters specifying which task to subscribe to - * @param eventConsumer consumer that will receive streaming events as they arrive - * @param errorConsumer consumer that will be called if an error occurs during streaming - * @param context optional client call context for the request (may be {@code null}) - * @throws A2AClientException if subscribing to the task fails for any reason - */ - void subscribeToTask(TaskIdParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException; - - /** - * Retrieve the extended AgentCard. - * - * @param context optional client call context for the request (may be {@code null}) - * @return the extended agent card - * @throws A2AClientException if retrieving the agent card fails for any reason - */ - AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException; - - /** - * Close the transport and release any associated resources. - */ - void close(); - -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java deleted file mode 100644 index f93954b40..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java +++ /dev/null @@ -1,95 +0,0 @@ -package io.a2a.client.transport.spi; - -import java.util.ArrayList; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; -import java.util.Collections; - -/** - * Base configuration class for A2A client transport protocols. - *

- * This abstract class provides common configuration functionality for all transport implementations - * (JSON-RPC, gRPC, REST). It manages request/response interceptors that can be used for logging, - * metrics, authentication, and other cross-cutting concerns. - *

- * Interceptors: Transport configurations support adding interceptors that can inspect and - * modify requests/responses. Interceptors are invoked in the order they were added: - *

{@code
- * // Example: Add logging and authentication interceptors
- * config.setInterceptors(List.of(
- *     new LoggingInterceptor(),
- *     new AuthenticationInterceptor("Bearer token")
- * ));
- * }
- *

- * Concrete implementations typically extend this class to add transport-specific configuration - * such as HTTP clients, gRPC channels, or connection pools. - *

- * Thread safety: Configuration instances should be treated as immutable after construction. - * The interceptor list is copied defensively to prevent external modification. - * - * @param the transport type this configuration is for - * @see ClientTransportConfigBuilder - * @see io.a2a.client.transport.spi.interceptors.ClientCallInterceptor - */ -public abstract class ClientTransportConfig { - - protected List interceptors = Collections.emptyList(); - protected Map parameters = Collections.emptyMap(); - - /** - * Set the list of request/response interceptors. - *

- * Interceptors are invoked in the order they appear in the list, allowing for - * controlled processing chains (e.g., authentication before logging). - *

- * The provided list is copied to prevent external modifications from affecting - * this configuration. - * - * @param interceptors the list of interceptors to use (will be copied) - * @see ClientTransportConfigBuilder#addInterceptor(ClientCallInterceptor) - */ - public void setInterceptors(List interceptors) { - this.interceptors = new ArrayList<>(interceptors); - } - - /** - * Get the list of configured interceptors. - *

- * Returns an unmodifiable view of the interceptor list. Attempting to modify - * the returned list will throw {@link UnsupportedOperationException}. - * - * @return an unmodifiable list of configured interceptors (never null, but may be empty) - */ - public List getInterceptors() { - return java.util.Collections.unmodifiableList(interceptors); - } - - /** - * Set the Map of config parameters. - * The provided map is copied to prevent external modifications from affecting - * this configuration. - * - * @param parameters the map of parameters to use (will be copied) - */ - public void setParameters(Map parameters) { - this.parameters = new HashMap<>(parameters); - } - - - /** - * Get the list of configured parameters. - *

- * Returns an unmodifiable view of the parameters map. Attempting to modify - * the returned map will throw {@link UnsupportedOperationException}. - * - * @return an unmodifiable map of configured parameters (never null, but may be empty) - */ - public Map getParameters() { - return java.util.Collections.unmodifiableMap(parameters); - } -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java deleted file mode 100644 index fabdab765..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java +++ /dev/null @@ -1,92 +0,0 @@ -package io.a2a.client.transport.spi; - -import java.util.ArrayList; -import java.util.List; - -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; - -/** - * Base builder class for constructing transport configuration instances. - *

- * This abstract builder provides common functionality for building transport configurations, - * particularly interceptor management. Concrete builders extend this class to add - * transport-specific configuration options. - *

- * Self-typed builder pattern: This class uses the "self-typed" or "curiously recurring - * template pattern" to enable method chaining in subclasses while maintaining type safety: - *

{@code
- * JSONRPCTransportConfig config = new JSONRPCTransportConfigBuilder()
- *     .addInterceptor(loggingInterceptor)  // Returns JSONRPCTransportConfigBuilder
- *     .httpClient(myHttpClient)            // Returns JSONRPCTransportConfigBuilder
- *     .build();                            // Returns JSONRPCTransportConfig
- * }
- *

- * Interceptor ordering: Interceptors are invoked in the order they were added: - *

{@code
- * builder
- *     .addInterceptor(authInterceptor)    // Runs first
- *     .addInterceptor(loggingInterceptor) // Runs second
- *     .addInterceptor(metricsInterceptor);// Runs third
- * }
- * - * @param the transport configuration type this builder creates - * @param the concrete builder type (for method chaining) - * @see ClientTransportConfig - * @see io.a2a.client.transport.spi.interceptors.ClientCallInterceptor - */ -public abstract class ClientTransportConfigBuilder, - B extends ClientTransportConfigBuilder> { - - protected List interceptors = new ArrayList<>(); - - /** - * Add a request/response interceptor to this transport configuration. - *

- * Interceptors can be used for cross-cutting concerns such as: - *

    - *
  • Logging requests and responses
  • - *
  • Adding authentication headers
  • - *
  • Collecting metrics and telemetry
  • - *
  • Request/response transformation
  • - *
  • Error handling and retry logic
  • - *
- *

- * Interceptors are invoked in the order they were added. If {@code interceptor} is - * {@code null}, this method is a no-op (for convenience in conditional addition). - *

- * Example: - *

{@code
-     * builder
-     *     .addInterceptor(new LoggingInterceptor())
-     *     .addInterceptor(authToken != null ? new AuthInterceptor(authToken) : null)
-     *     .addInterceptor(new MetricsInterceptor());
-     * }
- * - * @param interceptor the interceptor to add (null values are ignored) - * @return this builder for method chaining - * @see io.a2a.client.transport.spi.interceptors.ClientCallInterceptor - */ - public B addInterceptor(ClientCallInterceptor interceptor) { - if (interceptor != null) { - this.interceptors.add(interceptor); - } - - return (B) this; - } - - /** - * Build the transport configuration with all configured options. - *

- * Concrete implementations should: - *

    - *
  1. Validate required configuration (e.g., gRPC channel factory)
  2. - *
  3. Apply defaults for optional configuration (e.g., HTTP client)
  4. - *
  5. Create the configuration instance
  6. - *
  7. Transfer interceptors to the configuration
  8. - *
- * - * @return the configured transport configuration instance - * @throws IllegalStateException if required configuration is missing - */ - public abstract T build(); -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportProvider.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportProvider.java deleted file mode 100644 index a6224c8ed..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportProvider.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.a2a.client.transport.spi; - -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; - -/** - * Client transport provider interface. - */ -public interface ClientTransportProvider> { - - /** - * Create a client transport. - * - * @param clientTransportConfig the client transport config to use - * @param agentInterface the remote agent's interface - * @return the client transport - * @throws io.a2a.spec.A2AClientException if an error occurs trying to create the client - */ - T create(C clientTransportConfig, AgentCard agentCard, AgentInterface agentInterface) throws A2AClientException; - - /** - * Get the name of the client transport. - */ - String getTransportProtocol(); - - Class getTransportProtocolClass(); -} - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportWrapper.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportWrapper.java deleted file mode 100644 index 25dba33b9..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportWrapper.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.a2a.client.transport.spi; - -/** - * Service provider interface for wrapping client transports with additional functionality. - * Implementations can add cross-cutting concerns like tracing, metrics, logging, etc. - * - *

Wrappers are discovered via Java's ServiceLoader mechanism. To register a wrapper, - * create a file {@code META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper} - * containing the fully qualified class name of your implementation. - * - *

Wrappers are sorted by priority in descending order (highest priority first). - * This interface implements {@link Comparable} to enable natural sorting. - * - *

Example implementation: - *

{@code
- * public class TracingWrapper implements ClientTransportWrapper {
- *     @Override
- *     public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) {
- *         if (config.getParameters().containsKey("tracer")) {
- *             return new TracingTransport(transport, (Tracer) config.getParameters().get("tracer"));
- *         }
- *         return transport;
- *     }
- *
- *     @Override
- *     public int priority() {
- *         return 100; // Higher priority = wraps earlier (outermost)
- *     }
- * }
- * }
- */ -public interface ClientTransportWrapper extends Comparable { - - /** - * Wraps the given transport with additional functionality. - * - *

Implementations should check the configuration to determine if they should - * actually wrap the transport. If the wrapper is not applicable (e.g., required - * configuration is missing), return the original transport unchanged. - * - * @param transport the transport to wrap - * @param config the transport configuration, may contain wrapper-specific parameters - * @return the wrapped transport, or the original if wrapping is not applicable - */ - ClientTransport wrap(ClientTransport transport, ClientTransportConfig config); - - /** - * Returns the priority of this wrapper. Higher priority wrappers are applied first - * (wrap the transport earlier, resulting in being the outermost wrapper). - * - *

Default priority is 0. Suggested ranges: - *

    - *
  • 1000+ : Critical infrastructure (security, authentication) - *
  • 500-999: Observability (tracing, metrics, logging) - *
  • 100-499: Enhancement (caching, retry logic) - *
  • 0-99: Optional features - *
- * - * @return the priority value, higher values = higher priority - */ - default int priority() { - return 0; - } - - /** - * Compares this wrapper with another based on priority. - * Returns a negative integer, zero, or a positive integer as this wrapper - * has higher priority than, equal to, or lower priority than the specified wrapper. - * - *

Note: This comparison is reversed (higher priority comes first) to enable - * natural sorting in descending priority order. - * - * @param other the wrapper to compare to - * @return negative if this has higher priority, positive if lower, zero if equal - */ - @Override - default int compareTo(ClientTransportWrapper other) { - // Reverse comparison: higher priority should come first - return Integer.compare(other.priority(), this.priority()); - } -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallContext.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallContext.java deleted file mode 100644 index 288d7b54a..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallContext.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.a2a.client.transport.spi.interceptors; - -import java.util.Map; - -/** - * A context passed with each client call, allowing for call-specific. - * configuration and data passing. Such as authentication details or - * request deadlines. - */ -public class ClientCallContext { - - private final Map state; - private final Map headers; - - public ClientCallContext(Map state, Map headers) { - this.state = state; - this.headers = headers; - } - - public Map getState() { - return state; - } - - public Map getHeaders() { - return headers; - } -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallInterceptor.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallInterceptor.java deleted file mode 100644 index b8a8de797..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/ClientCallInterceptor.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.a2a.client.transport.spi.interceptors; - -import java.util.Map; - -import io.a2a.spec.AgentCard; -import org.jspecify.annotations.Nullable; - -/** - * An abstract base class for client-side call interceptors. - * Interceptors can inspect and modify requests before they are sent, - * which is ideal for concerns like authentication, logging, or tracing. - */ -public abstract class ClientCallInterceptor { - - /** - * Intercept a client call before the request is sent. - * - * @param methodName the name of the protocol method (e.g., 'message/send') - * @param payload the request payload - * @param headers the headers to use - * @param agentCard the agent card (may be {@code null}) - * @param clientCallContext the {@code ClientCallContext} for this call (may be {@code null}) - * @return the potentially modified payload and headers - */ - public abstract PayloadAndHeaders intercept(String methodName, @Nullable Object payload, Map headers, - @Nullable AgentCard agentCard, @Nullable ClientCallContext clientCallContext); -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java deleted file mode 100644 index 7f8075312..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.a2a.client.transport.spi.interceptors; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.jspecify.annotations.Nullable; - -public class PayloadAndHeaders { - - private final @Nullable Object payload; - private final Map headers; - - public PayloadAndHeaders(@Nullable Object payload, @Nullable Map headers) { - this.payload = payload; - this.headers = headers == null ? Collections.emptyMap() : new HashMap<>(headers); - } - - public @Nullable Object getPayload() { - return payload; - } - - public Map getHeaders() { - return headers; - } -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java deleted file mode 100644 index 2b073d413..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptor.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.a2a.client.transport.spi.interceptors.auth; - -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; -import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.AgentCard; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; -import org.jspecify.annotations.Nullable; - -/** - * An interceptor that automatically adds authentication details to requests - * based on the agent's security schemes and the credentials available. - */ -public class AuthInterceptor extends ClientCallInterceptor { - - private static final String BEARER_SCHEME = "bearer"; - public static final String AUTHORIZATION = "Authorization"; - private static final String BEARER = "Bearer "; - private final CredentialService credentialService; - - public AuthInterceptor(final CredentialService credentialService) { - this.credentialService = credentialService; - } - - @Override - public PayloadAndHeaders intercept(String methodName, @Nullable Object payload, Map headers, - @Nullable AgentCard agentCard, @Nullable ClientCallContext clientCallContext) { - Map updatedHeaders = new HashMap<>(headers == null ? new HashMap<>() : headers); - if (agentCard == null || agentCard.securityRequirements()== null || agentCard.securitySchemes() == null) { - return new PayloadAndHeaders(payload, updatedHeaders); - } - for (SecurityRequirement requirement : agentCard.securityRequirements()) { - if (requirement == null) { - continue; - } - for (String securitySchemeName : requirement.schemes().keySet()) { - String credential = credentialService.getCredential(securitySchemeName, clientCallContext); - if (credential != null && agentCard.securitySchemes().containsKey(securitySchemeName)) { - SecurityScheme securityScheme = agentCard.securitySchemes().get(securitySchemeName); - if (securityScheme == null) { - continue; - } - if (securityScheme instanceof HTTPAuthSecurityScheme httpAuthSecurityScheme) { - if (httpAuthSecurityScheme.scheme().toLowerCase(Locale.ROOT).equals(BEARER_SCHEME)) { - updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); - return new PayloadAndHeaders(payload, updatedHeaders); - } - } else if (securityScheme instanceof OAuth2SecurityScheme - || securityScheme instanceof OpenIdConnectSecurityScheme) { - updatedHeaders.put(AUTHORIZATION, getBearerValue(credential)); - return new PayloadAndHeaders(payload, updatedHeaders); - } else if (securityScheme instanceof APIKeySecurityScheme apiKeySecurityScheme) { - updatedHeaders.put(apiKeySecurityScheme.name(), credential); - return new PayloadAndHeaders(payload, updatedHeaders); - } - } - } - } - return new PayloadAndHeaders(payload, updatedHeaders); - } - - private static String getBearerValue(String credential) { - return BEARER + credential; - } -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/CredentialService.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/CredentialService.java deleted file mode 100644 index 949ea8087..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/CredentialService.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.client.transport.spi.interceptors.auth; - -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import org.jspecify.annotations.Nullable; - -/** - * Used to retrieve credentials. - */ -public interface CredentialService { - - /** - * Retrieves a credential (e.g., token) for a security scheme. - * - * @param securitySchemeName the name of the security scheme - * @param clientCallContext the client call context, which may be {@code null}. - * @return the credential or {@code null} if the credential could not be retrieved - */ - @Nullable String getCredential(String securitySchemeName, @Nullable ClientCallContext clientCallContext); -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java deleted file mode 100644 index f6db9662a..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/InMemoryContextCredentialService.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.a2a.client.transport.spi.interceptors.auth; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import org.jspecify.annotations.Nullable; - -/** - * A simple in-memory store for session-keyed credentials. - * This class uses the 'sessionId' from the {@code ClientCallContext} state to - * store and retrieve credentials - */ -public class InMemoryContextCredentialService implements CredentialService { - - private static final String SESSION_ID = "sessionId"; - - // maps a sessionId to a map of security scheme names to credentials - private final ConcurrentMap> credentialStore; - - public InMemoryContextCredentialService() { - credentialStore = new ConcurrentHashMap<>(); - } - - @Override - public @Nullable String getCredential(String securitySchemeName, - @Nullable ClientCallContext clientCallContext) { - if (clientCallContext == null || !clientCallContext.getState().containsKey(SESSION_ID)) { - // no credential to retrieve - return null; - } - - Object sessionIdObj = clientCallContext.getState().get(SESSION_ID); - if (! (sessionIdObj instanceof String sessionId)) { - return null; - } - Map sessionCredentials = credentialStore.get(sessionId); - if (sessionCredentials == null) { - return null; - } - return sessionCredentials.get(securitySchemeName); - } - - /** - * Method to populate the in-memory credential service. - * - * @param sessionId the session ID - * @param securitySchemeName the name of the security scheme - * @param credential the credential string - */ - public void setCredential(String sessionId, String securitySchemeName, String credential) { - credentialStore.computeIfAbsent(sessionId, k -> new ConcurrentHashMap<>()).put(securitySchemeName, credential); - } -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/package-info.java deleted file mode 100644 index 85b061333..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/auth/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.spi.interceptors.auth; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/package-info.java deleted file mode 100644 index d85534d28..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.spi.interceptors; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/package-info.java deleted file mode 100644 index f2185d0c9..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.spi; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java deleted file mode 100644 index b6051bf41..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/AbstractSSEEventListener.java +++ /dev/null @@ -1,120 +0,0 @@ -package io.a2a.client.transport.spi.sse; - -import java.util.concurrent.Future; -import java.util.function.Consumer; -import java.util.logging.Logger; - -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.jspecify.annotations.Nullable; - -/** - * Abstract base class for SSE event listeners that provides common functionality - * for handling Server-Sent Events across different transport implementations. - *

- * This class implements the Template Method pattern, where subclasses provide - * the specific message parsing logic while the base class handles common concerns - * like error handling and connection lifecycle management. - */ -public abstract class AbstractSSEEventListener { - - private static final Logger log = Logger.getLogger(AbstractSSEEventListener.class.getName()); - - private final Consumer eventHandler; - private final @Nullable Consumer errorHandler; - - /** - * Creates a new SSE event listener with the specified handlers. - * - * @param eventHandler Handler for processing streaming events - * @param errorHandler Optional handler for processing errors - */ - protected AbstractSSEEventListener(Consumer eventHandler, - @Nullable Consumer errorHandler) { - this.eventHandler = eventHandler; - this.errorHandler = errorHandler; - } - - /** - * Gets the event handler for processing streaming events. - * - * @return The event handler - */ - protected Consumer getEventHandler() { - return eventHandler; - } - - /** - * Gets the error handler for processing errors. - * - * @return The error handler, or null if not set - */ - protected @Nullable Consumer getErrorHandler() { - return errorHandler; - } - - /** - * Handles incoming SSE messages. Subclasses must implement the specific - * parsing logic for their transport protocol. - * - * @param message The raw message string from the SSE stream - * @param completableFuture Optional future for controlling the SSE connection - */ - public abstract void onMessage(String message, @Nullable Future completableFuture); - - /** - * Handles errors that occur during SSE streaming. - * This method is identical across all implementations. - * - * @param throwable The error that occurred - * @param future Optional future for closing the SSE connection - */ - public void onError(Throwable throwable, @Nullable Future future) { - if (errorHandler != null) { - errorHandler.accept(throwable); - } - if (future != null) { - future.cancel(true); // close SSE channel - } - } - - /** - * Processes a parsed streaming event and handles auto-close logic for final events. - * This method encapsulates the common logic for handling events and determining - * when to close the SSE connection. - * - * @param event The parsed streaming event - * @param future Optional future for closing the SSE connection - */ - protected void handleEvent(StreamingEventKind event, @Nullable Future future) { - eventHandler.accept(event); - - // Client-side auto-close on final events to prevent connection leaks - // Handles both TaskStatusUpdateEvent and Task objects with final states - // This covers late subscriptions to completed tasks and ensures no connection leaks - if (shouldAutoClose(event) && future != null) { - log.fine("Auto-closing SSE connection for final event: " + event.getClass().getSimpleName()); - future.cancel(true); // close SSE channel - } - } - - /** - * Determines if the SSE connection should be automatically closed based on the event type. - * The connection is closed when receiving final task states to prevent connection leaks. - * - * @param event The streaming event to check - * @return true if the connection should be closed, false otherwise - */ - protected boolean shouldAutoClose(StreamingEventKind event) { - if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { - return true; - } - if (event instanceof Task task) { - TaskState state = task.status().state(); - return state.isFinal(); - } - return false; - } -} diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java deleted file mode 100644 index 1083bc32e..000000000 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/sse/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.transport.spi.sse; - -import org.jspecify.annotations.NullMarked; - diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java deleted file mode 100644 index ed29dafab..000000000 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java +++ /dev/null @@ -1,329 +0,0 @@ -package io.a2a.client.transport.spi.interceptors.auth; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; -import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OAuthFlows; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class AuthInterceptorTest { - - private InMemoryContextCredentialService credentialStore; - private AuthInterceptor authInterceptor; - - @BeforeEach - void setUp() { - credentialStore = new InMemoryContextCredentialService(); - authInterceptor = new AuthInterceptor(credentialStore); - } - - private static class HeaderInterceptor extends ClientCallInterceptor { - private final String headerName; - private final String headerValue; - - public HeaderInterceptor(String headerName, String headerValue) { - this.headerName = headerName; - this.headerValue = headerValue; - } - - @Override - public PayloadAndHeaders intercept(String methodName, Object payload, Map headers, - AgentCard agentCard, ClientCallContext clientCallContext) { - Map updatedHeaders = new HashMap<>(headers); - updatedHeaders.put(headerName, headerValue); - return new PayloadAndHeaders(payload, updatedHeaders); - } - } - - private static class AuthTestCase { - final String url; - final String sessionId; - final String schemeName; - final String credential; - final SecurityScheme securityScheme; - final String expectedHeaderKey; - final String expectedHeaderValue; - - AuthTestCase(String url, String sessionId, String schemeName, String credential, - SecurityScheme securityScheme, String expectedHeaderKey, String expectedHeaderValue) { - this.url = url; - this.sessionId = sessionId; - this.schemeName = schemeName; - this.credential = credential; - this.securityScheme = securityScheme; - this.expectedHeaderKey = expectedHeaderKey; - this.expectedHeaderValue = expectedHeaderValue; - } - } - - @Test - public void testAPIKeySecurityScheme() { - AuthTestCase authTestCase = new AuthTestCase( - "http://agent.com/rpc", - "session-id", - APIKeySecurityScheme.TYPE, - "secret-api-key", - new APIKeySecurityScheme(APIKeySecurityScheme.Location.HEADER, "x-api-key", "API Key authentication"), - "x-api-key", - "secret-api-key" - ); - testSecurityScheme(authTestCase); - } - - @Test - public void testOAuth2SecurityScheme() { - AuthTestCase authTestCase = new AuthTestCase( - "http://agent.com/rpc", - "session-id", - OAuth2SecurityScheme.TYPE, - "secret-oauth-access-token", - new OAuth2SecurityScheme(OAuthFlows.builder().build(), "OAuth2 authentication", null), - "Authorization", - "Bearer secret-oauth-access-token" - ); - testSecurityScheme(authTestCase); - } - - @Test - public void testOidcSecurityScheme() { - AuthTestCase authTestCase = new AuthTestCase( - "http://agent.com/rpc", - "session-id", - OpenIdConnectSecurityScheme.TYPE, - "secret-oidc-id-token", - new OpenIdConnectSecurityScheme("http://provider.com/.well-known/openid-configuration", "OIDC authentication"), - "Authorization", - "Bearer secret-oidc-id-token" - ); - testSecurityScheme(authTestCase); - } - - @Test - public void testBearerSecurityScheme() { - AuthTestCase authTestCase = new AuthTestCase( - "http://agent.com/rpc", - "session-id", - "bearer", - "bearer-token-123", - new HTTPAuthSecurityScheme(null, "bearer", "Bearer token authentication"), - "Authorization", - "Bearer bearer-token-123" - ); - testSecurityScheme(authTestCase); - } - - private void testSecurityScheme(AuthTestCase authTestCase) { - credentialStore.setCredential(authTestCase.sessionId, authTestCase.schemeName, authTestCase.credential); - - AgentCard agentCard = createAgentCard(authTestCase.schemeName, authTestCase.securityScheme); - Map requestPayload = Map.of("test", "payload"); - Map headers = Map.of(); - ClientCallContext context = new ClientCallContext(Map.of("sessionId", authTestCase.sessionId), Map.of()); - - PayloadAndHeaders result = authInterceptor.intercept( - "SendMessage", - requestPayload, - headers, - agentCard, - context - ); - - assertEquals(requestPayload, result.getPayload()); - assertEquals(authTestCase.expectedHeaderValue, result.getHeaders().get(authTestCase.expectedHeaderKey)); - } - - @Test - void testAuthInterceptorWithoutAgentCard() { - Map requestPayload = Map.of("foo", "bar"); - Map headers = Map.of("foo", "bar"); - - PayloadAndHeaders result = authInterceptor.intercept( - "SendMessage", - requestPayload, - headers, - null, // no agent card - new ClientCallContext(Map.of(), Map.of()) - ); - - // should be unchanged - assertEquals(requestPayload, result.getPayload()); - assertEquals(headers, result.getHeaders()); - } - - @Test - void testInMemoryContextCredentialStore() { - String sessionId = "session-id"; - String schemeName = "test-scheme"; - String credential = "test-token"; - - credentialStore.setCredential(sessionId, schemeName, credential); - ClientCallContext context = new ClientCallContext(Map.of("sessionId", sessionId), Map.of()); - String retrievedCredential = credentialStore.getCredential(schemeName, context); - assertEquals(credential, retrievedCredential); - - // wrong session ID - ClientCallContext wrongContext = new ClientCallContext(Map.of("sessionId", "wrong-session"), Map.of()); - retrievedCredential = credentialStore.getCredential(schemeName, wrongContext); - assertNull(retrievedCredential); - - retrievedCredential = credentialStore.getCredential(schemeName, null); - assertNull(retrievedCredential); - - // no session ID in context - ClientCallContext emptyContext = new ClientCallContext(Map.of(), Map.of()); - retrievedCredential = credentialStore.getCredential(schemeName, emptyContext); - assertNull(retrievedCredential); - - String newCredential = "new-token"; - credentialStore.setCredential(sessionId, schemeName, newCredential); - retrievedCredential = credentialStore.getCredential(schemeName, context); - assertEquals(newCredential, retrievedCredential); - } - - @Test - void testCustomInterceptor() { - String headerName = "X-Test-Header"; - String headerValue = "Test-Value-123"; - HeaderInterceptor interceptor = new HeaderInterceptor(headerName, headerValue); - - Map payload = Map.of("test", "payload"); - Map headers = Map.of(); - - PayloadAndHeaders result = interceptor.intercept( - "SendMessage", - payload, - headers, - null, - null - ); - - assertEquals(payload, result.getPayload()); - assertEquals(headerValue, result.getHeaders().get(headerName)); - } - - @Test - void testAvailableSecuritySchemeNotInAgentCardSecuritySchemes() { - String schemeName = "missing"; - String sessionId = "session-id"; - String credential = "dummy-token"; - - credentialStore.setCredential(sessionId, schemeName, credential); - - // Create agent card with security requirement but no scheme definition - AgentCard agentCard = AgentCard.builder() - .name("missing") - .description("Uses missing scheme definition") - .supportedInterfaces(List.of(new AgentInterface("jsonrpc", "http://agent.com/rpc", ""))) - .version("1.0") - .capabilities(AgentCapabilities.builder().build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .securityRequirements(List.of(SecurityRequirement.builder().scheme(schemeName, List.of()).build())) - .securitySchemes(Map.of()) // no security schemes - .build(); - - Map requestPayload = Map.of("foo", "bar"); - Map headers = Map.of("fizz", "buzz"); - ClientCallContext context = new ClientCallContext(Map.of("sessionId", sessionId), Map.of()); - - PayloadAndHeaders result = authInterceptor.intercept( - "SendMessage", - requestPayload, - headers, - agentCard, - context - ); - - assertEquals(requestPayload, result.getPayload()); - assertEquals(headers, result.getHeaders()); - } - - @Test - void testNoCredentialAvailable() { - String schemeName = "apikey"; - SecurityScheme securityScheme = new APIKeySecurityScheme(APIKeySecurityScheme.Location.HEADER, "X-API-Key", "API Key authentication"); - AgentCard agentCard = createAgentCard(schemeName, securityScheme); - - Map requestPayload = Map.of("test", "payload"); - Map headers = Map.of(); - ClientCallContext context = new ClientCallContext(Map.of("sessionId", "session-id"), Map.of()); - - PayloadAndHeaders result = authInterceptor.intercept( - "SendMessage", - requestPayload, - headers, - agentCard, - context - ); - - assertEquals(requestPayload, result.getPayload()); - assertEquals(headers, result.getHeaders()); // headers should be unchanged - } - - @Test - void testNoAgentCardSecuritySpecified() { - // Arrange - AgentCard agentCard = AgentCard.builder() - .name("nosecuritybot") - .description("A bot with no security requirements") - .supportedInterfaces(List.of(new AgentInterface("jsonrpc", "http://agent.com/rpc"))) - .version("1.0") - .capabilities(AgentCapabilities.builder().build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .securityRequirements(null) // no security info - .build(); - - Map requestPayload = Map.of("test", "payload"); - Map headers = Map.of(); - ClientCallContext context = new ClientCallContext(Map.of("sessionId", "session-id"), Map.of()); - - PayloadAndHeaders result = authInterceptor.intercept( - "SendMessage", - requestPayload, - headers, - agentCard, - context - ); - - assertEquals(requestPayload, result.getPayload()); - assertEquals(headers, result.getHeaders()); - } - - /** - * Helper method to create an AgentCard with specified security scheme. - */ - private AgentCard createAgentCard(String schemeName, SecurityScheme securityScheme) { - return AgentCard.builder() - .name(schemeName + "bot") - .description("A bot that uses " + schemeName) - .supportedInterfaces(List.of(new AgentInterface("jsonrpc", "http://agent.com/rpc"))) - .version("1.0") - .capabilities(AgentCapabilities.builder().build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .securityRequirements(List.of(SecurityRequirement.builder().scheme(schemeName, List.of()).build())) - .securitySchemes(Map.of(schemeName, securityScheme)) - .build(); - } -} diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java deleted file mode 100644 index 9dd643df3..000000000 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/sse/SSEEventListenerTest.java +++ /dev/null @@ -1,294 +0,0 @@ -package io.a2a.client.transport.spi.sse; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.jspecify.annotations.Nullable; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -/** - * Tests for BaseSSEEventListener abstract class. - * Tests the common functionality provided by the base class for handling events and errors. - */ -public class SSEEventListenerTest { - - private static final String TEST_TASK_ID = "task-123"; - private static final String TEST_CONTEXT_ID = "ctx-456"; - private static final String TEST_MESSAGE_ID = "msg-123"; - private static final String TEST_TEXT = "test"; - - /** - * Concrete implementation of BaseSSEEventListener for testing. - * Simulates parsing by directly calling handleEvent with provided test data. - */ - private static class TestSSEEventListener extends AbstractSSEEventListener { - private StreamingEventKind eventToHandle; - - public TestSSEEventListener(Consumer eventHandler, - @Nullable Consumer errorHandler) { - super(eventHandler, errorHandler); - } - - @Override - public void onMessage(String message, @Nullable Future completableFuture) { - if (eventToHandle != null) { - handleEvent(eventToHandle, completableFuture); - } - } - - public void setEventToHandle(StreamingEventKind event) { - this.eventToHandle = event; - } - } - - /** - * Mock Future implementation that captures cancel calls. - */ - private static class CancelCapturingFuture implements Future { - private boolean cancelHandlerCalled = false; - - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - cancelHandlerCalled = true; - return true; - } - - @Override - public boolean isCancelled() { - return cancelHandlerCalled; - } - - @Override - public boolean isDone() { - return false; - } - - @Override - public Void get() { - return null; - } - - @Override - public Void get(long timeout, TimeUnit unit) { - return null; - } - - public boolean wasCancelled() { - return cancelHandlerCalled; - } - } - - // Helper methods for creating test objects - - private static Message createMessage(Message.Role role) { - return Message.builder() - .role(role) - .messageId(TEST_MESSAGE_ID) - .contextId(TEST_CONTEXT_ID) - .parts(java.util.List.of(new TextPart(TEST_TEXT))) - .build(); - } - - private static Task createTask(TaskState state) { - return Task.builder() - .id(TEST_TASK_ID) - .contextId(TEST_CONTEXT_ID) - .status(new TaskStatus(state)) - .build(); - } - - private static TaskStatusUpdateEvent createTaskStatusUpdateEvent(TaskState state, boolean isFinal) { - // Use constructor since Builder doesn't have isFinal method - return new TaskStatusUpdateEvent( - TEST_TASK_ID, - new TaskStatus(state), - TEST_CONTEXT_ID, - isFinal, - null - ); - } - - private static TestSSEEventListener createListenerWithEventCapture(AtomicReference eventCapture) { - return new TestSSEEventListener(eventCapture::set, null); - } - - private static TestSSEEventListener createListenerWithErrorCapture(AtomicReference errorCapture) { - return new TestSSEEventListener(event -> {}, errorCapture::set); - } - - private static TestSSEEventListener createBasicListener() { - return new TestSSEEventListener(event -> {}, null); - } - - // Tests - - @Test - public void testHandleEventCallsEventHandler() { - AtomicReference receivedEvent = new AtomicReference<>(); - TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - - Message message = createMessage(Message.Role.ROLE_USER); - - listener.setEventToHandle(message); - listener.onMessage(TEST_TEXT, null); - - assertNotNull(receivedEvent.get()); - assertEquals(message, receivedEvent.get()); - } - - @Test - public void testHandleEventWithNullErrorHandler() { - AtomicReference receivedEvent = new AtomicReference<>(); - TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - - Task task = createTask(TaskState.TASK_STATE_WORKING); - - listener.setEventToHandle(task); - listener.onMessage(TEST_TEXT, null); - - assertNotNull(receivedEvent.get()); - } - - @Test - public void testOnErrorCallsErrorHandler() { - AtomicReference receivedError = new AtomicReference<>(); - TestSSEEventListener listener = createListenerWithErrorCapture(receivedError); - - IllegalStateException testError = new IllegalStateException("Test error"); - - listener.onError(testError, null); - - assertNotNull(receivedError.get()); - assertEquals(testError, receivedError.get()); - } - - @Test - public void testOnErrorWithNullErrorHandler() { - TestSSEEventListener listener = createBasicListener(); - - // Should not throw even with null error handler - listener.onError(new RuntimeException("Test error"), null); - } - - @Test - public void testOnErrorCancelsFuture() { - AtomicBoolean errorHandlerCalled = new AtomicBoolean(false); - TestSSEEventListener listener = new TestSSEEventListener( - event -> {}, - error -> errorHandlerCalled.set(true) - ); - - CancelCapturingFuture future = new CancelCapturingFuture(); - - listener.onError(new RuntimeException("Test error"), future); - - assertTrue(errorHandlerCalled.get()); - assertTrue(future.wasCancelled()); - } - - @Test - public void testShouldAutoCloseWithFinalTaskStatusUpdateEvent() { - TestSSEEventListener listener = createBasicListener(); - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); - - assertTrue(listener.shouldAutoClose(finalEvent)); - } - - @Test - public void testShouldAutoCloseWithNonFinalTaskStatusUpdateEvent() { - TestSSEEventListener listener = createBasicListener(); - TaskStatusUpdateEvent nonFinalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_WORKING, false); - - assertFalse(listener.shouldAutoClose(nonFinalEvent)); - } - - @ParameterizedTest - @EnumSource(value = TaskState.class, names = {"TASK_STATE_COMPLETED", "TASK_STATE_FAILED", "TASK_STATE_CANCELED"}) - public void testShouldAutoCloseWithFinalTaskStates(TaskState finalState) { - TestSSEEventListener listener = createBasicListener(); - Task task = createTask(finalState); - - assertTrue(listener.shouldAutoClose(task), - "Task with state " + finalState + " should trigger auto-close"); - } - - @ParameterizedTest - @EnumSource(value = TaskState.class, names = {"TASK_STATE_WORKING", "TASK_STATE_SUBMITTED"}) - public void testShouldAutoCloseWithNonFinalTaskStates(TaskState nonFinalState) { - TestSSEEventListener listener = createBasicListener(); - Task task = createTask(nonFinalState); - - assertFalse(listener.shouldAutoClose(task), - "Task with state " + nonFinalState + " should not trigger auto-close"); - } - - @Test - public void testShouldAutoCloseWithMessage() { - TestSSEEventListener listener = createBasicListener(); - Message message = createMessage(Message.Role.ROLE_AGENT); - - assertFalse(listener.shouldAutoClose(message)); - } - - @Test - public void testAutoCloseCancelsFutureForFinalEvent() { - AtomicReference receivedEvent = new AtomicReference<>(); - TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); - CancelCapturingFuture future = new CancelCapturingFuture(); - - listener.setEventToHandle(finalEvent); - listener.onMessage(TEST_TEXT, future); - - assertNotNull(receivedEvent.get()); - assertEquals(finalEvent, receivedEvent.get()); - assertTrue(future.wasCancelled()); - } - - @Test - public void testAutoCloseDoesNotCancelFutureForNonFinalEvent() { - AtomicReference receivedEvent = new AtomicReference<>(); - TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - - Message message = createMessage(Message.Role.ROLE_AGENT); - CancelCapturingFuture future = new CancelCapturingFuture(); - - listener.setEventToHandle(message); - listener.onMessage(TEST_TEXT, future); - - assertNotNull(receivedEvent.get()); - assertFalse(future.wasCancelled()); - } - - @Test - public void testAutoCloseWithNullFuture() { - AtomicReference receivedEvent = new AtomicReference<>(); - TestSSEEventListener listener = createListenerWithEventCapture(receivedEvent); - - TaskStatusUpdateEvent finalEvent = createTaskStatusUpdateEvent(TaskState.TASK_STATE_COMPLETED, true); - - // Should not throw with null future - listener.setEventToHandle(finalEvent); - listener.onMessage(TEST_TEXT, null); - - assertNotNull(receivedEvent.get()); - } -} \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml deleted file mode 100644 index 9ceff362f..000000000 --- a/common/pom.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - a2a-java-sdk-common - - jar - - Java SDK A2A Common - Java SDK for the Agent2Agent Protocol (A2A) - Common - - - - org.slf4j - slf4j-api - - - - \ No newline at end of file diff --git a/common/src/main/java/io/a2a/common/A2AErrorMessages.java b/common/src/main/java/io/a2a/common/A2AErrorMessages.java deleted file mode 100644 index 2801a2b4e..000000000 --- a/common/src/main/java/io/a2a/common/A2AErrorMessages.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.a2a.common; - -public final class A2AErrorMessages { - - private A2AErrorMessages() { - // Prevent instantiation - } - - public static final String AUTHENTICATION_FAILED = "Authentication failed: Client credentials are missing or invalid"; - public static final String AUTHORIZATION_FAILED = "Authorization failed: Client does not have permission for the operation"; -} diff --git a/common/src/main/java/io/a2a/common/A2AHeaders.java b/common/src/main/java/io/a2a/common/A2AHeaders.java deleted file mode 100644 index f050333aa..000000000 --- a/common/src/main/java/io/a2a/common/A2AHeaders.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.a2a.common; - -/** - * Common A2A protocol headers and constants. - */ -public final class A2AHeaders { - - /** - * HTTP header name for A2A protocol version. - * Used to communicate the protocol version that the client is using. - */ - public static final String X_A2A_VERSION = "X-A2A-Version"; - - /** - * HTTP header name for A2A extensions. - * Used to communicate which extensions are requested by the client. - */ - public static final String X_A2A_EXTENSIONS = "X-A2A-Extensions"; - - /** - * HTTP header name for a push notification token. - */ - public static final String X_A2A_NOTIFICATION_TOKEN = "X-A2A-Notification-Token"; - - private A2AHeaders() { - // Utility class - } -} diff --git a/common/src/main/java/io/a2a/common/package-info.java b/common/src/main/java/io/a2a/common/package-info.java deleted file mode 100644 index f1c6af6c4..000000000 --- a/common/src/main/java/io/a2a/common/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.common; - -import org.jspecify.annotations.NullMarked; - diff --git a/common/src/main/java/io/a2a/util/Assert.java b/common/src/main/java/io/a2a/util/Assert.java deleted file mode 100644 index 0c375a36b..000000000 --- a/common/src/main/java/io/a2a/util/Assert.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.a2a.util; - -import org.jspecify.annotations.Nullable; - -public final class Assert { - - /** - * Check that the named parameter is not {@code null}. Use a standard exception message if it is. - * - * @param name the parameter name - * @param value the parameter value - * @param the value type - * @return the value that was passed in - * @throws IllegalArgumentException if the value is {@code null} - */ - public static @NotNull T checkNotNullParam(String name, @Nullable T value) throws IllegalArgumentException { - checkNotNullParamChecked("name", name); - if (value == null) { - throw new IllegalArgumentException("Parameter '" + name + "' may not be null"); - } - return value; - } - - private static void checkNotNullParamChecked(final String name, final @Nullable T value) { - if (value == null) { - throw new IllegalArgumentException("Parameter '" + name + "' may not be null"); - } - } - - public static void isNullOrStringOrInteger(@Nullable Object value) { - if (! (value == null || value instanceof String || value instanceof Integer)) { - throw new IllegalArgumentException("Id must be null, a String, or an Integer"); - } - } - -} diff --git a/common/src/main/java/io/a2a/util/NotNull.java b/common/src/main/java/io/a2a/util/NotNull.java deleted file mode 100644 index 3146117f3..000000000 --- a/common/src/main/java/io/a2a/util/NotNull.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.a2a.util; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.CLASS) -@Target({ ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PARAMETER }) -@Documented -public @interface NotNull { -} \ No newline at end of file diff --git a/common/src/main/java/io/a2a/util/package-info.java b/common/src/main/java/io/a2a/util/package-info.java deleted file mode 100644 index 769e16337..000000000 --- a/common/src/main/java/io/a2a/util/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.util; - -import org.jspecify.annotations.NullMarked; - diff --git a/examples/cloud-deployment/README.md b/examples/cloud-deployment/README.md deleted file mode 100644 index fe146a6e9..000000000 --- a/examples/cloud-deployment/README.md +++ /dev/null @@ -1,593 +0,0 @@ -# A2A Cloud Deployment Example - -This example demonstrates deploying an A2A agent to Kubernetes with: -- **Multiple pods** (2 replicas) for load balancing -- **PostgreSQL database** for persistent task storage -- **Kafka event replication** for cross-pod event streaming -- **JSON-RPC transport** for client-server communication - -Note that the aim of this example is just to demonstrate how to set up a2a-java in a cloud environment. Hence, it doesn't do anything with an LLM, but shows that it can be configured to work in a cloud, or other distributed, environment. - -## Architecture - -``` - localhost:8080 - (extraPortMappings) - ▲ - │ -┌───────────────────────────────────┼───────────────────────┐ -│ Kubernetes Cluster (Kind) │ │ -│ │ │ -│ ┌───────────▼──────────┐ │ -│ │ Service (NodePort) │ │ -│ │ Round-Robin │ │ -│ └───────────┬──────────┘ │ -│ │ │ -│ ┌───────────┴──────────┐ │ -│ ▼ ▼ │ -│ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ A2A Agent │ │ A2A Agent │ │ -│ │ Pod 1 │ │ Pod 2 │ │ -│ └────┬────────┬───┘ └───┬────────┬────┘ │ -│ │ │ │ │ │ -│ │ └───────────┘ │ │ -│ │ │ │ -│ ▼ ▼ │ -│ ┌────────────────┐ ┌─────────────────┐ │ -│ │ PostgreSQL DB │ │ Kafka │ │ -│ │ (Task Store) │ │ (Queue Manager)│ │ -│ └────────────────┘ └─────────────────┘ │ -│ ▲ ▲ │ -│ │ │ │ -│ Task Persistence Event Replication │ -└───────────────────────────────────────────────────────────┘ - ▲ - │ - ┌──────┴──────┐ - │ Client │ - │ (External) │ - └─────────────┘ -``` - -## What This Example Demonstrates - -1. **Load Balancing**: Messages sent to the service are distributed across pods via round-robin -2. **Event Replication**: Events from one pod are replicated to other pods via Kafka -3. **Task Persistence**: Task state is stored in PostgreSQL and shared across all pods -4. **Streaming Subscriptions**: Clients can subscribe to task updates and receive events from any pod -5. **Fire-and-Forget Pattern**: Tasks remain in WORKING state until explicitly completed -6. **Command-Based Protocol**: Simple message protocol ("start", "process", "complete") - -## Prerequisites - -- **Kind** (Kubernetes IN Docker) v0.20+ -- **kubectl** (v1.27+) -- **Maven** (3.8+) -- **Java** 17+ -- **Container runtime**: Docker or Podman - -## Quick Start - -### 1. Install Prerequisites - -**Install Kind:** -See https://kind.sigs.k8s.io/docs/user/quick-start/ for installation instructions. - -**Install kubectl:** -See https://kubernetes.io/docs/tasks/tools/ for installation instructions. - -### 2. Deploy the Stack - -The deployment script will automatically create the Kind cluster and deploy all components: - -```bash -cd scripts -./deploy.sh -``` - -**If using Podman instead of Docker:** -```bash -./deploy.sh --container-tool podman -``` - -Note that using Kind with Podman on Linux may have some occasional issues due to Kind's experimental support for Podman. In our testing, a reboot normally solves this. - -**Troubleshooting entity operator timeout:** - -In some environments (particularly Linux with Podman), the Kafka entity operator may not start properly, causing deployment to timeout while waiting for Kafka to be ready. If you encounter this issue, you can skip the entity operator wait: - -```bash -export SKIP_ENTITY_OPERATOR_WAIT=true -./deploy.sh --container-tool podman -``` - -This tells the script to: -- Check only the Kafka broker pod (not the full Kafka resource with entity operator) -- Poll the Kafka broker directly to verify topic creation (instead of waiting for the topic operator) - -The entity operator manages topic and user resources, but the broker handles the actual message streaming. Skipping the entity operator wait does not affect the demo's core functionality. - -The script will: -- Create Kind cluster with local registry support (if not already exists) -- Set up local container registry (localhost:5001) -- Install Strimzi Kafka operator -- Deploy PostgreSQL -- Deploy Kafka cluster (using KRaft mode) -- Build and deploy the A2A agent (2 pods) - -**Note:** You don't need to manually create the Kind cluster - the script handles everything. - -### 3. Verify Deployment - -```bash -./verify.sh -``` - -Expected output: -``` -✓ Namespace 'a2a-demo' exists -✓ PostgreSQL is running -✓ Kafka is ready -✓ Agent pods are running (2/2 ready) -✓ Agent service exists -``` - -### 4. Test Multi-Pod Behavior - -#### Understanding the NodePort Setup - -The agent service uses **NodePort** with Kind **extraPortMappings** to expose the service: - -- Kind maps **host port 8080** → **node port 30080** (configured in `kind-config.yaml`) -- Kubernetes Service maps **NodePort 30080** → **pod port 8080** (configured in `k8s/05-agent-deployment.yaml`) -- Result: Access the agent at **http://localhost:8080** from your host machine - -This approach provides the same round-robin load balancing as a real LoadBalancer but works consistently across all platforms (macOS, Linux, Windows, and CI environments like GitHub Actions). - -#### Run the Test Client - -```bash -cd ../server -mvn test-compile exec:java \ - -Dexec.mainClass="io.a2a.examples.cloud.A2ACloudExampleClient" \ - -Dexec.classpathScope=test \ - -Dagent.url="http://localhost:8080" -``` - -Expected output: -``` -============================================= -A2A Cloud Deployment Example Client -============================================= - -Agent URL: http://localhost:8080 -Process messages: 8 -Message interval: 1500ms - -Fetching agent card... -✓ Agent: Cloud Deployment Demo Agent -✓ Description: Demonstrates A2A multi-pod deployment with Kafka event replication, PostgreSQL persistence, and round-robin load balancing across Kubernetes pods - -Client task ID: cloud-test-1234567890 - -Step 1: Sending 'start' to create task... -✓ Task created: - State: WORKING - -Step 2: Subscribing to task for streaming updates... -✓ Subscribed to task updates - Artifact #1: Started by a2a-agent-7b8f9c-abc12 - → Pod: a2a-agent-7b8f9c-abc12 (Total unique pods: 1) - -Step 3: Sending 8 'process' messages (interval: 1500ms)... --------------------------------------------- -✓ Process message 1 sent - Artifact #2: Processed by a2a-agent-7b8f9c-xyz34 - → Pod: a2a-agent-7b8f9c-xyz34 (Total unique pods: 2) -✓ Process message 2 sent - Artifact #3: Processed by a2a-agent-7b8f9c-abc12 - → Pod: a2a-agent-7b8f9c-abc12 (Total unique pods: 2) -✓ Process message 3 sent - Artifact #4: Processed by a2a-agent-7b8f9c-xyz34 - → Pod: a2a-agent-7b8f9c-xyz34 (Total unique pods: 2) -... - -Waiting for process artifacts to arrive... - -Step 4: Sending 'complete' to finalize task... -✓ Complete message sent, task state: COMPLETED - Artifact #10: Completed by a2a-agent-7b8f9c-abc12 - -Waiting for task to complete... - Task reached final state: COMPLETED - -============================================= -Test Results -============================================= -Total artifacts received: 10 -Unique pods observed: 2 -Pod names: [a2a-agent-7b8f9c-abc12, a2a-agent-7b8f9c-xyz34] - -✓ TEST PASSED - Successfully demonstrated multi-pod processing! - Messages were handled by 2 different pods. - This proves that: - - Load balancing is working (round-robin across pods) - - Event replication is working (subscriber sees events from all pods) - - Database persistence is working (task state shared across pods) -``` - -## How It Works - -### Agent Implementation - -The agent (`CloudAgentExecutorProducer`) implements a command-based protocol: - -```java -@Override -public void execute(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { - String messageText = extractTextFromMessage(context.getMessage()).trim().toLowerCase(); - - // Get pod name from Kubernetes downward API - String podName = System.getenv("POD_NAME"); - - if ("complete".equals(messageText)) { - // Completion trigger - add final artifact and complete - String artifactText = "Completed by " + podName; - List> parts = List.of(new TextPart(artifactText)); - agentEmitter.addArtifact(parts); - agentEmitter.complete(); // Transition to COMPLETED state - } else if (context.getTask() == null) { - // Initial "start" message - create task in SUBMITTED → WORKING state - agentEmitter.submit(); - agentEmitter.startWork(); - String artifactText = "Started by " + podName; - List> parts = List.of(new TextPart(artifactText)); - agentEmitter.addArtifact(parts); - } else { - // Subsequent "process" messages - add artifacts (fire-and-forget, stays WORKING) - String artifactText = "Processed by " + podName; - List> parts = List.of(new TextPart(artifactText)); - agentEmitter.addArtifact(parts); - } -} -``` - -**Message Protocol**: -- `"start"`: Initialize task (SUBMITTED → WORKING), adds "Started by {pod-name}" -- `"process"`: Add artifact "Processed by {pod-name}" (fire-and-forget, stays WORKING) -- `"complete"`: Add artifact "Completed by {pod-name}" and transition to COMPLETED - -### Cloud-Native Components - -1. **Database Persistence** (`JpaDatabaseTaskStore`): - - Tasks are stored in PostgreSQL - - All pods read/write to the same database - - Ensures task state is consistent across pods. - - More information about `JpaDatabaseTaskStore` can be found [here](../../extras/task-store-database-jpa/README.md) - - -2. **Event Replication** (`ReplicatedQueueManager` + `ReactiveMessagingReplicationStrategy`): - - Events are published to Kafka topic `a2a-replicated-events`. - - All pods subscribe to the same topic - - Events from pod A are replicated to pod B's queue - - More information about `ReplicatedQueueManager` and `ReactiveMessagingReplicationStrategy` can be found [here](../../extras/queue-manager-replicated/README.md) - - -3. **Configuration** (`application.properties`): - - Database URL, credentials - - Kafka bootstrap servers - - Reactive Messaging channel configuration - -### Load Balancing Flow - -``` -Client sends "start"/"process"/"complete" message - ↓ -Kubernetes Service (round-robin) - ↓ -Pod A or Pod B (alternates) - ↓ -AgentExecutor processes command - ↓ -Enqueues artifact with pod name ("Started by"/"Processed by"/"Completed by") - ↓ -Event published to Kafka topic (a2a-replicated-events) - ↓ -All pods receive replicated event - ↓ -Streaming subscriber receives artifact (regardless of which pod sent it) -``` - -## Configuration - -### Environment Variables - -The following environment variables are configured via ConfigMap (`k8s/04-agent-configmap.yaml`): - -| Variable | Description | Example | -|----------|-------------|---------| -| `POD_NAME` | Pod name (from downward API) | `a2a-agent-7b8f9c-abc12` | -| `DATABASE_URL` | PostgreSQL JDBC URL | `jdbc:postgresql://postgres.a2a-demo.svc.cluster.local:5432/a2a` | -| `DATABASE_USER` | Database username | `a2a` | -| `DATABASE_PASSWORD` | Database password | `a2a` | -| `KAFKA_BOOTSTRAP_SERVERS` | Kafka brokers | `a2a-kafka-kafka-bootstrap.kafka.svc.cluster.local:9092` | -| `AGENT_URL` | Public agent URL | `http://localhost:8080` | - -### Scaling - -To change the number of agent pods, edit `k8s/05-agent-deployment.yaml`: - -```yaml -spec: - replicas: 2 # Change to desired number -``` - -Then apply: -```bash -kubectl apply -f k8s/05-agent-deployment.yaml -``` - -## Troubleshooting - -### Pods Not Starting - -**Check pod status:** -```bash -kubectl get pods -n a2a-demo -kubectl describe pod -n a2a-demo -kubectl logs -n a2a-demo -``` - -**Common issues:** -- **ImagePullBackOff**: Image not pushed to local registry - - Solution: Ensure registry is running and push completed successfully - - Check: `curl http://localhost:5001/v2/_catalog` should list the image -- **CrashLoopBackOff**: Application startup failure - - Check logs: `kubectl logs -n a2a-demo` - - Common causes: Database not ready, Kafka not ready - -### Registry Issues - -**Registry not accessible:** - -```bash -# Verify registry is running -docker ps | grep kind-registry -# or for Podman: -podman ps | grep kind-registry - -# Verify registry is accessible -curl http://localhost:5001/v2/ -# Should return: {} - -# List images in registry -curl http://localhost:5001/v2/_catalog -``` - -**Image push failures:** -- Check registry container is running -- For Podman: Ensure you use `--tls-verify=false` flag when pushing -- Restart registry if needed: `docker/podman stop kind-registry && docker/podman start kind-registry` - -### Database Connection Failures - -**Check PostgreSQL status:** -```bash -kubectl get pods -n a2a-demo -l app=postgres -kubectl logs -n a2a-demo -``` - -**Test connection from agent pod:** -```bash -kubectl exec -it -n a2a-demo -- bash -# Inside pod: -curl telnet://postgres.a2a-demo.svc.cluster.local:5432 -``` - -**Common issues:** -- PostgreSQL pod not ready: Wait for it to become Ready -- Wrong credentials: Check ConfigMap values match PostgreSQL config - -### Kafka Connection Failures - -**Check Kafka status:** -```bash -kubectl get kafka -n a2a-demo -kubectl get pods -n a2a-demo -l strimzi.io/cluster=a2a-kafka -``` - -**Common issues:** -- Kafka not ready: Kafka takes 2-5 minutes to start fully - - Wait for `kubectl wait --for=condition=Ready kafka/a2a-kafka -n a2a-demo` -- Topic not created: Kafka auto-creates topics on first publish - -### Test Client Failures - -**Connection refused errors:** -```bash -# Verify agent card is accessible via NodePort -curl http://localhost:8080/.well-known/agent-card.json - -# If this fails, check: -# 1. Agent pods are ready -kubectl get pods -n a2a-demo -l app=a2a-agent - -# 2. Service exists and has correct NodePort -kubectl get svc a2a-agent-service -n a2a-demo - -# Expected output: -# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -# a2a-agent-service NodePort 10.96.123.45 8080:30080/TCP 5m - -# 3. Verify Kind extraPortMappings are configured -docker ps | grep kind-control-plane -# or for Podman: -podman ps | grep kind-control-plane -``` - -**Only seeing 1 pod:** -- Check both pods are Running: `kubectl get pods -n a2a-demo -l app=a2a-agent` -- The test client creates fresh HTTP connections for each message to force load balancing -- If still seeing 1 pod, check service sessionAffinity is set to `None` (see `k8s/05-agent-deployment.yaml`) -- Try increasing PROCESS_MESSAGE_COUNT in test client for more samples - -### Strimzi Installation Issues - -**Strimzi operator not ready:** -```bash -kubectl get pods -n kafka -kubectl logs -n kafka -``` - -**CRD not found:** -```bash -# Check if Kafka CRD is installed -kubectl get crd kafkas.kafka.strimzi.io - -# If missing, reinstall Strimzi -kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka -``` - -### Kind Resource Issues - -**Insufficient resources:** -Kind uses your Docker/Podman resources. Increase Docker Desktop memory/CPU limits if needed. - -**Disk space:** -```bash -# Check disk usage inside Kind node -docker exec -it kind-control-plane df -h -# or for Podman: -podman exec -it kind-control-plane df -h - -# Clean up old images -docker system prune -a # or: podman system prune -a -``` - -## Cleanup - -To remove all deployed resources: - -```bash -cd scripts -./cleanup.sh -``` - -This will delete: -- A2A agent deployment and service -- Kafka cluster -- PostgreSQL -- Namespace `a2a-demo` - -To also remove Strimzi operator: -```bash -kubectl delete namespace kafka -``` - -To delete the Kind cluster: -```bash -kind delete cluster -``` - -### Complete Clean Slate - -For a completely fresh start (useful for testing from scratch): - -```bash -# Delete Kind cluster -kind delete cluster - -# Remove local registry container -docker stop kind-registry && docker rm kind-registry -# or for Podman: -podman stop kind-registry && podman rm kind-registry - -# Optional: Clean up container images -docker system prune -a # or: podman system prune -a -``` - -Then re-run `./deploy.sh` to start fresh. - -## Project Structure - -``` -cloud-deployment/ -├── server/ -│ ├── src/main/java/io/a2a/examples/cloud/ -│ │ ├── CloudAgentCardProducer.java # Agent card configuration -│ │ └── CloudAgentExecutorProducer.java # Agent business logic -│ ├── src/main/resources/ -│ │ └── application.properties # Application configuration -│ ├── src/test/java/io/a2a/examples/cloud/ -│ │ └── A2ACloudExampleClient.java # Test client -│ ├── pom.xml # Maven dependencies -│ └── Dockerfile # Container image -├── k8s/ -│ ├── 00-namespace.yaml # Kubernetes namespace -│ ├── 01-postgres.yaml # PostgreSQL deployment -│ ├── 02-kafka.yaml # Strimzi Kafka cluster -│ ├── 03-kafka-topic.yaml # Kafka topic -│ ├── 04-agent-configmap.yaml # Configuration -│ └── 05-agent-deployment.yaml # Agent deployment + service -├── scripts/ -│ ├── deploy.sh # Automated deployment -│ ├── verify.sh # Health checks -│ └── cleanup.sh # Resource cleanup -└── README.md # This file -``` - -## Key Dependencies - -From `pom.xml`: - -```xml - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - - - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - - - io.github.a2asdk - a2a-java-queue-manager-replication-mp-reactive - - - - - io.quarkus - quarkus-messaging-kafka - -``` - -## Next Steps - -- **Production deployment**: Use a real Kubernetes cluster (e.g. OpenShift) with proper LoadBalancer or Ingress -- **Secrets management**: Use Kubernetes Secrets for credentials -- **Monitoring**: Add Prometheus metrics and Grafana dashboards -- **Autoscaling**: Configure Horizontal Pod Autoscaler based on CPU/memory -- **Persistent storage**: Use PersistentVolumes for PostgreSQL in production -- **TLS**: Enable TLS for Kafka and PostgreSQL connections -- **Resource limits**: Fine-tune CPU/memory requests and limits - -## References - -- [A2A Protocol Specification](https://github.com/a2aproject/a2a) -- [Kind Quick Start](https://kind.sigs.k8s.io/docs/user/quick-start/) -- [Kind Local Registry](https://kind.sigs.k8s.io/docs/user/local-registry/) -- [Kind extraPortMappings](https://kind.sigs.k8s.io/docs/user/configuration/#extra-port-mappings) -- [Strimzi Kafka Operator](https://strimzi.io/) -- [Quarkus Reactive Messaging](https://quarkus.io/guides/kafka) -- [Kubernetes Downward API](https://kubernetes.io/docs/concepts/workloads/pods/downward-api/) diff --git a/examples/cloud-deployment/k8s/00-namespace.yaml b/examples/cloud-deployment/k8s/00-namespace.yaml deleted file mode 100644 index f232b6816..000000000 --- a/examples/cloud-deployment/k8s/00-namespace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: a2a-demo diff --git a/examples/cloud-deployment/k8s/01-postgres.yaml b/examples/cloud-deployment/k8s/01-postgres.yaml deleted file mode 100644 index b81e94d54..000000000 --- a/examples/cloud-deployment/k8s/01-postgres.yaml +++ /dev/null @@ -1,74 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: postgres-config - namespace: a2a-demo -data: - POSTGRES_DB: a2a - POSTGRES_USER: a2a - POSTGRES_PASSWORD: a2a ---- -apiVersion: v1 -kind: Service -metadata: - name: postgres - namespace: a2a-demo -spec: - selector: - app: postgres - ports: - - port: 5432 - targetPort: 5432 - clusterIP: None ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: postgres - namespace: a2a-demo -spec: - serviceName: postgres - replicas: 1 - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - spec: - containers: - - name: postgres - image: mirror.gcr.io/postgres:16 - ports: - - containerPort: 5432 - name: postgres - envFrom: - - configMapRef: - name: postgres-config - volumeMounts: - - name: postgres-storage - mountPath: /var/lib/postgresql/data - resources: - requests: - memory: "256Mi" - cpu: "250m" - limits: - memory: "512Mi" - cpu: "500m" - readinessProbe: - exec: - command: - - pg_isready - - -U - - a2a - initialDelaySeconds: 5 - periodSeconds: 5 - volumeClaimTemplates: - - metadata: - name: postgres-storage - spec: - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: 1Gi diff --git a/examples/cloud-deployment/k8s/02-kafka.yaml b/examples/cloud-deployment/k8s/02-kafka.yaml deleted file mode 100644 index 044aeb1ac..000000000 --- a/examples/cloud-deployment/k8s/02-kafka.yaml +++ /dev/null @@ -1,65 +0,0 @@ ---- -# KafkaNodePool for KRaft mode -apiVersion: kafka.strimzi.io/v1beta2 -kind: KafkaNodePool -metadata: - name: broker - namespace: kafka - labels: - strimzi.io/cluster: a2a-kafka -spec: - replicas: 1 - roles: - - broker - - controller - storage: - type: ephemeral - resources: - requests: - memory: "512Mi" - cpu: "250m" - limits: - memory: "1Gi" - cpu: "500m" ---- -# Kafka cluster -apiVersion: kafka.strimzi.io/v1beta2 -kind: Kafka -metadata: - name: a2a-kafka - namespace: kafka - annotations: - strimzi.io/node-pools: enabled - strimzi.io/kraft: enabled -spec: - kafka: - version: 4.0.0 - metadataVersion: 4.0-IV0 - listeners: - - name: plain - port: 9092 - type: internal - tls: false - config: - offsets.topic.replication.factor: 1 - transaction.state.log.replication.factor: 1 - transaction.state.log.min.isr: 1 - default.replication.factor: 1 - min.insync.replicas: 1 - entityOperator: - topicOperator: - resources: - requests: - memory: "128Mi" - cpu: "100m" - limits: - memory: "256Mi" - cpu: "200m" - userOperator: - resources: - requests: - memory: "128Mi" - cpu: "100m" - limits: - memory: "256Mi" - cpu: "200m" diff --git a/examples/cloud-deployment/k8s/03-kafka-topic.yaml b/examples/cloud-deployment/k8s/03-kafka-topic.yaml deleted file mode 100644 index 2fa7fca9c..000000000 --- a/examples/cloud-deployment/k8s/03-kafka-topic.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -# Kafka topic for A2A event replication -apiVersion: kafka.strimzi.io/v1beta2 -kind: KafkaTopic -metadata: - name: a2a-replicated-events - namespace: kafka - labels: - strimzi.io/cluster: a2a-kafka -spec: - partitions: 3 - replicas: 1 - config: - retention.ms: 3600000 # 1 hour retention - segment.bytes: 1073741824 - cleanup.policy: delete diff --git a/examples/cloud-deployment/k8s/04-agent-configmap.yaml b/examples/cloud-deployment/k8s/04-agent-configmap.yaml deleted file mode 100644 index 4c7195d82..000000000 --- a/examples/cloud-deployment/k8s/04-agent-configmap.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: agent-config - namespace: a2a-demo -data: - DATABASE_URL: "jdbc:postgresql://postgres.a2a-demo.svc.cluster.local:5432/a2a" - DATABASE_USER: "a2a" - DATABASE_PASSWORD: "a2a" - KAFKA_BOOTSTRAP_SERVERS: "a2a-kafka-kafka-bootstrap.kafka.svc.cluster.local:9092" - AGENT_URL: "http://localhost:8080" diff --git a/examples/cloud-deployment/k8s/05-agent-deployment.yaml b/examples/cloud-deployment/k8s/05-agent-deployment.yaml deleted file mode 100644 index 27d141ad2..000000000 --- a/examples/cloud-deployment/k8s/05-agent-deployment.yaml +++ /dev/null @@ -1,96 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: a2a-agent - namespace: a2a-demo - labels: - app: a2a-agent -spec: - replicas: 2 - selector: - matchLabels: - app: a2a-agent - template: - metadata: - labels: - app: a2a-agent - spec: - containers: - - name: a2a-agent - image: localhost:5001/a2a-cloud-deployment:latest - # Always pull to ensure latest image is used when rebuilding with :latest tag - # For production, use digest-based image references (e.g., @sha256:...) - imagePullPolicy: Always - ports: - - containerPort: 8080 - name: http - protocol: TCP - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: DATABASE_URL - valueFrom: - configMapKeyRef: - name: agent-config - key: DATABASE_URL - - name: DATABASE_USER - valueFrom: - configMapKeyRef: - name: agent-config - key: DATABASE_USER - - name: DATABASE_PASSWORD - valueFrom: - configMapKeyRef: - name: agent-config - key: DATABASE_PASSWORD - - name: KAFKA_BOOTSTRAP_SERVERS - valueFrom: - configMapKeyRef: - name: agent-config - key: KAFKA_BOOTSTRAP_SERVERS - - name: AGENT_URL - valueFrom: - configMapKeyRef: - name: agent-config - key: AGENT_URL - resources: - requests: - memory: "512Mi" - cpu: "250m" - limits: - memory: "1Gi" - cpu: "500m" - livenessProbe: - httpGet: - path: /health/live - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health/ready - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 5 - timeoutSeconds: 3 - failureThreshold: 3 ---- -apiVersion: v1 -kind: Service -metadata: - name: a2a-agent-service - namespace: a2a-demo -spec: - selector: - app: a2a-agent - ports: - - protocol: TCP - port: 8080 # Service port inside cluster - targetPort: 8080 # Pod port - nodePort: 30080 # Fixed NodePort (mapped to host port 8080 via Kind config) - type: NodePort - sessionAffinity: None # Ensures round-robin load balancing diff --git a/examples/cloud-deployment/kind-config.yaml b/examples/cloud-deployment/kind-config.yaml deleted file mode 100644 index 821027be6..000000000 --- a/examples/cloud-deployment/kind-config.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Kind cluster configuration for A2A Cloud Deployment Example -# This config enables: -# - Local registry integration -# - NodePort service access via extraPortMappings -# - Sufficient resources for PostgreSQL, Kafka, and 2 agent pods - -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 - -# Enable local registry support -containerdConfigPatches: -- |- - [plugins."io.containerd.grpc.v1.cri".registry] - config_path = "/etc/containerd/certs.d" - -nodes: -# Single control-plane node is sufficient for this demo -- role: control-plane - # Map host port 8080 to NodePort 30080 for agent service access - extraPortMappings: - - containerPort: 30080 # NodePort on Kubernetes node - hostPort: 8080 # Accessible on localhost:8080 - listenAddress: "0.0.0.0" - protocol: TCP diff --git a/examples/cloud-deployment/scripts/cleanup.sh b/examples/cloud-deployment/scripts/cleanup.sh deleted file mode 100755 index 7d97840c6..000000000 --- a/examples/cloud-deployment/scripts/cleanup.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -echo "============================================" -echo "A2A Cloud Deployment - Cleanup Script" -echo "============================================" -echo "" - -# Color codes -GREEN='\033[0;32m' -RED='\033[0;31m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Parse command line arguments -CONTAINER_TOOL="docker" -while [[ $# -gt 0 ]]; do - case $1 in - --container-tool) - CONTAINER_TOOL="$2" - shift 2 - ;; - *) - echo -e "${RED}Unknown option: $1${NC}" - echo "Usage: $0 [--container-tool docker|podman]" - exit 1 - ;; - esac -done - -# Configure Kind to use podman if specified -if [ "$CONTAINER_TOOL" = "podman" ]; then - export KIND_EXPERIMENTAL_PROVIDER=podman -fi - -echo -e "${YELLOW}This will delete all resources in the a2a-demo namespace and the Kind cluster${NC}" -read -p "Are you sure you want to continue? (y/N) " -n 1 -r -echo "" - -if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Cleanup cancelled" - exit 0 -fi - -echo "" -echo "Deleting A2A Agent..." -kubectl delete -f ../k8s/05-agent-deployment.yaml --ignore-not-found=true - -echo "" -echo "Deleting ConfigMap..." -kubectl delete -f ../k8s/04-agent-configmap.yaml --ignore-not-found=true - -echo "" -echo "Deleting Kafka topic..." -kubectl delete -f ../k8s/03-kafka-topic.yaml --ignore-not-found=true - -echo "" -echo "Deleting Kafka..." -kubectl delete -f ../k8s/02-kafka.yaml --ignore-not-found=true - -echo "" -echo "Deleting PostgreSQL..." -kubectl delete -f ../k8s/01-postgres.yaml --ignore-not-found=true - -echo "" -echo "Deleting namespace..." -kubectl delete -f ../k8s/00-namespace.yaml --ignore-not-found=true - -echo "" -echo "Deleting Kind cluster..." -kind delete cluster - -echo "" -echo "Stopping and removing registry container..." -$CONTAINER_TOOL stop kind-registry > /dev/null 2>&1 || true -$CONTAINER_TOOL rm kind-registry > /dev/null 2>&1 || true - -echo "" -echo -e "${GREEN}Cleanup completed${NC}" -echo "" -echo -e "${YELLOW}Note: Strimzi operator was not removed${NC}" -echo "To remove Strimzi operator, run:" -echo " kubectl delete namespace kafka" diff --git a/examples/cloud-deployment/scripts/deploy.sh b/examples/cloud-deployment/scripts/deploy.sh deleted file mode 100755 index fff2a6061..000000000 --- a/examples/cloud-deployment/scripts/deploy.sh +++ /dev/null @@ -1,358 +0,0 @@ -#!/bin/bash -set -e - -echo "=========================================" -echo "A2A Cloud Deployment - Deployment Script" -echo "=========================================" -echo "" - -# Color codes for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Parse command line arguments -CONTAINER_TOOL="docker" -while [[ $# -gt 0 ]]; do - case $1 in - --container-tool) - CONTAINER_TOOL="$2" - shift 2 - ;; - *) - echo -e "${RED}Unknown option: $1${NC}" - echo "Usage: $0 [--container-tool docker|podman]" - exit 1 - ;; - esac -done - -echo "Container tool: $CONTAINER_TOOL" -echo "" - -# Configure Kind to use podman if specified -if [ "$CONTAINER_TOOL" = "podman" ]; then - export KIND_EXPERIMENTAL_PROVIDER=podman - echo "Configured Kind to use podman provider" - echo "" -fi - -# Check if Kind is installed -if ! command -v kind &> /dev/null; then - echo -e "${RED}Error: Kind is not installed${NC}" - echo "Please install Kind first: https://kind.sigs.k8s.io/docs/user/quick-start/#installation" - exit 1 -fi - -# Check if kubectl is installed -if ! command -v kubectl &> /dev/null; then - echo -e "${RED}Error: kubectl is not installed${NC}" - echo "Please install kubectl first: https://kubernetes.io/docs/tasks/tools/" - exit 1 -fi - -# Setup local registry -echo "Setting up local registry..." -REG_NAME='kind-registry' -REG_PORT='5001' - -# Create registry container if it doesn't exist -if [ "$($CONTAINER_TOOL inspect -f '{{.State.Running}}' "${REG_NAME}" 2>/dev/null || true)" != 'true' ]; then - echo "Creating registry container..." - $CONTAINER_TOOL run \ - -d --restart=always -p "127.0.0.1:${REG_PORT}:5000" --network bridge --name "${REG_NAME}" \ - mirror.gcr.io/library/registry:2 - echo -e "${GREEN}✓ Registry container created${NC}" -else - echo -e "${GREEN}✓ Registry container already running${NC}" -fi - -# Create Kind cluster if it doesn't exist -echo "" -if ! kind get clusters 2>/dev/null | grep -q '^kind$'; then - echo "Creating Kind cluster..." - kind create cluster --config=../kind-config.yaml - echo -e "${GREEN}✓ Kind cluster created${NC}" -else - # Check if cluster is healthy by trying to get nodes - if ! kubectl get nodes &>/dev/null; then - echo -e "${RED}Error: Existing Kind cluster is not healthy${NC}" - echo "" - echo "The cluster exists but is not responding. This usually means:" - echo " - The cluster containers are stopped" - echo " - The cluster is in a corrupted state" - echo "" - echo "To fix this, delete the cluster and re-run this script:" - echo " kind delete cluster" - echo " ./deploy.sh" - echo "" - exit 1 - else - echo -e "${GREEN}✓ Kind cluster already exists and is healthy${NC}" - fi -fi - -# Configure registry on cluster nodes -echo "" -echo "Configuring registry on cluster nodes..." -REGISTRY_DIR="/etc/containerd/certs.d/localhost:${REG_PORT}" -for node in $(kind get nodes); do - $CONTAINER_TOOL exec "${node}" mkdir -p "${REGISTRY_DIR}" - cat < /dev/null 2>&1; then - echo -e "${GREEN}✓ Registry accessible at localhost:${REG_PORT}${NC}" -else - echo -e "${RED}ERROR: Registry not accessible${NC}" - exit 1 -fi - -# Build the project -echo "" -echo "Building the project..." -cd ../server -mvn clean package -DskipTests -echo -e "${GREEN}✓ Project built successfully${NC}" - -# Build and push container image to local registry -REGISTRY="localhost:${REG_PORT}" -echo "" -echo "Building container image..." -$CONTAINER_TOOL build -t ${REGISTRY}/a2a-cloud-deployment:latest . -echo -e "${GREEN}✓ Container image built${NC}" - -echo "Pushing image to local registry..." -if [ "$CONTAINER_TOOL" = "podman" ]; then - $CONTAINER_TOOL push --tls-verify=false ${REGISTRY}/a2a-cloud-deployment:latest -else - $CONTAINER_TOOL push ${REGISTRY}/a2a-cloud-deployment:latest -fi -echo -e "${GREEN}✓ Image pushed to registry${NC}" - -# Go back to scripts directory -cd ../scripts - -# Install Strimzi operator if not already installed -echo "" -echo "Checking for Strimzi operator..." - -# Ensure kafka namespace exists -if ! kubectl get namespace kafka > /dev/null 2>&1; then - echo "Creating kafka namespace..." - kubectl create namespace kafka -fi - -if ! kubectl get crd kafkas.kafka.strimzi.io > /dev/null 2>&1; then - echo "Installing Strimzi operator..." - kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka - - echo "Waiting for Strimzi operator deployment to be created..." - for i in {1..30}; do - if kubectl get deployment strimzi-cluster-operator -n kafka > /dev/null 2>&1; then - echo "Deployment found" - break - fi - if [ $i -eq 30 ]; then - echo -e "${RED}ERROR: Deployment not found after 30 seconds${NC}" - exit 1 - fi - sleep 1 - done - - echo "Waiting for Strimzi operator to be ready..." - kubectl wait --for=condition=Available deployment/strimzi-cluster-operator -n kafka --timeout=300s - kubectl wait --for=condition=Ready pod -l name=strimzi-cluster-operator -n kafka --timeout=300s - echo -e "${GREEN}✓ Strimzi operator installed${NC}" -else - echo -e "${GREEN}✓ Strimzi operator already installed${NC}" -fi - -# Create namespace -echo "" -echo "Creating namespace..." -kubectl apply -f ../k8s/00-namespace.yaml -echo -e "${GREEN}✓ Namespace created${NC}" - -# Deploy PostgreSQL -echo "" -echo "Deploying PostgreSQL..." -kubectl apply -f ../k8s/01-postgres.yaml -echo "Waiting for PostgreSQL to be ready..." - -# Wait for pod to be created (StatefulSet takes time to create pod) -for i in {1..30}; do - if kubectl get pod -l app=postgres -n a2a-demo 2>/dev/null | grep -q postgres; then - echo "PostgreSQL pod found, waiting for ready state..." - break - fi - if [ $i -eq 30 ]; then - echo -e "${RED}ERROR: PostgreSQL pod not created after 30 seconds${NC}" - kubectl get statefulset -n a2a-demo - exit 1 - fi - sleep 1 -done - -# Now wait for pod to be ready -kubectl wait --for=condition=Ready pod -l app=postgres -n a2a-demo --timeout=120s -echo -e "${GREEN}✓ PostgreSQL deployed${NC}" - -# Deploy Kafka -echo "" -echo "Deploying Kafka..." -kubectl apply -f ../k8s/02-kafka.yaml -echo "Waiting for Kafka to be ready (using KRaft mode, typically 2-3 minutes. Timeout is 10 minutes)..." - -# Check if we should skip entity operator wait (workaround for some environments) -if [ "${SKIP_ENTITY_OPERATOR_WAIT}" = "true" ]; then - echo -e "${YELLOW}⚠ SKIP_ENTITY_OPERATOR_WAIT is set - checking broker pod only${NC}" - - # Wait for broker pod to be ready (skip entity operator check) - for i in {1..60}; do - echo "Checking Kafka broker status (attempt $i/60)..." - kubectl get pods -n kafka -l strimzi.io/cluster=a2a-kafka 2>/dev/null || true - - if kubectl wait --for=condition=Ready pod/a2a-kafka-broker-0 -n kafka --timeout=5s 2>/dev/null; then - echo -e "${GREEN}✓ Kafka broker pod is ready${NC}" - echo -e "${YELLOW}⚠ Entity operator may not be ready, but this does not affect functionality${NC}" - break - fi - - if [ $i -eq 60 ]; then - echo -e "${RED}ERROR: Timeout waiting for Kafka broker${NC}" - kubectl get pods -n kafka -l strimzi.io/cluster=a2a-kafka - kubectl describe pod a2a-kafka-broker-0 -n kafka 2>/dev/null || true - exit 1 - fi - - sleep 5 - done -else - echo -e "${YELLOW} If waiting for Kafka times out, run ./cleanup.sh, and retry having set 'SKIP_ENTITY_OPERATOR_WAIT=true'${NC}" - # Standard wait for full Kafka resource (includes entity operator) - for i in {1..60}; do - echo "Checking Kafka status (attempt $i/60)..." - kubectl get kafka -n kafka -o wide 2>/dev/null || true - kubectl get pods -n kafka -l strimzi.io/cluster=a2a-kafka 2>/dev/null || true - - if kubectl wait --for=condition=Ready kafka/a2a-kafka -n kafka --timeout=10s 2>/dev/null; then - echo -e "${GREEN}✓ Kafka deployed${NC}" - break - fi - - if [ $i -eq 60 ]; then - echo -e "${RED}ERROR: Timeout waiting for Kafka${NC}" - kubectl describe kafka/a2a-kafka -n kafka - kubectl get events -n kafka --sort-by='.lastTimestamp' - exit 1 - fi - done -fi - -# Create Kafka Topic for event replication -echo "" -echo "Creating Kafka topic for event replication..." -kubectl apply -f ../k8s/03-kafka-topic.yaml - -if [ "${SKIP_ENTITY_OPERATOR_WAIT}" = "true" ]; then - echo -e "${YELLOW}⚠ SKIP_ENTITY_OPERATOR_WAIT is set - polling Kafka broker for topic${NC}" - echo " Topic operator may not be ready, waiting for broker to create topic. This check can take several minutes..." - - # Wait for topic to actually exist in Kafka broker (not just CRD) - for i in {1..30}; do - if kubectl exec a2a-kafka-broker-0 -n kafka -- \ - /opt/kafka/bin/kafka-topics.sh --list --bootstrap-server localhost:9092 2>/dev/null | \ - grep -q "a2a-replicated-events"; then - echo -e "${GREEN}✓ Topic exists in Kafka broker${NC}" - break - fi - if [ $i -eq 30 ]; then - echo -e "${RED}ERROR: Topic not found in broker after 30 attempts${NC}" - exit 1 - fi - sleep 2 - done -else - echo "Waiting for Kafka topic to be ready..." - if kubectl wait --for=condition=Ready kafkatopic/a2a-replicated-events -n kafka --timeout=60s; then - echo -e "${GREEN}✓ Kafka topic created${NC}" - else - echo -e "${RED}ERROR: Timeout waiting for Kafka topic${NC}" - echo -e "${YELLOW}The topic operator may not be ready in this environment.${NC}" - echo -e "${YELLOW}Run ./cleanup.sh, then retry with: export SKIP_ENTITY_OPERATOR_WAIT=true${NC}" - exit 1 - fi -fi - -# Deploy Agent ConfigMap -echo "" -echo "Deploying Agent ConfigMap..." -kubectl apply -f ../k8s/04-agent-configmap.yaml -echo -e "${GREEN}✓ ConfigMap deployed${NC}" - -# Deploy Agent -if [ "${SKIP_AGENT_DEPLOY}" != "true" ]; then - echo "" - echo "Deploying A2A Agent..." - kubectl apply -f ../k8s/05-agent-deployment.yaml - - echo "Waiting for Agent pods to be ready..." - kubectl wait --for=condition=Ready pod -l app=a2a-agent -n a2a-demo --timeout=120s - echo -e "${GREEN}✓ Agent deployed${NC}" -else - echo "" - echo -e "${YELLOW}⚠ Skipping agent deployment (SKIP_AGENT_DEPLOY=true)${NC}" - echo " ConfigMap has been deployed, you can manually deploy the agent with:" - echo " kubectl apply -f ../k8s/05-agent-deployment.yaml" -fi - -echo "" -echo -e "${GREEN}=========================================${NC}" -echo -e "${GREEN}Deployment completed successfully!${NC}" -echo -e "${GREEN}=========================================${NC}" -echo "" -echo "To verify the deployment, run:" -echo " ./verify.sh" -echo "" -echo "To access the agent (via NodePort):" -echo " curl http://localhost:8080/.well-known/agent-card.json" -echo "" -echo "To run the test client (demonstrating load balancing):" -echo " cd ../server" -echo " mvn test-compile exec:java -Dexec.classpathScope=test \\" -echo " -Dexec.mainClass=\"io.a2a.examples.cloud.A2ACloudExampleClient\" \\" -echo " -Dagent.url=\"http://localhost:8080\"" diff --git a/examples/cloud-deployment/scripts/verify.sh b/examples/cloud-deployment/scripts/verify.sh deleted file mode 100755 index b9905b0d7..000000000 --- a/examples/cloud-deployment/scripts/verify.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/bash - -echo "============================================" -echo "A2A Cloud Deployment - Verification Script" -echo "============================================" -echo "" - -# Color codes -GREEN='\033[0;32m' -RED='\033[0;31m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Check namespace exists -echo "Checking namespace..." -if kubectl get namespace a2a-demo > /dev/null 2>&1; then - echo -e "${GREEN}✓ Namespace 'a2a-demo' exists${NC}" -else - echo -e "${RED}✗ Namespace 'a2a-demo' not found${NC}" - exit 1 -fi - -# Check PostgreSQL -echo "" -echo "Checking PostgreSQL..." -POSTGRES_READY=$(kubectl get pods -n a2a-demo -l app=postgres -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}' 2>/dev/null) -if [ "$POSTGRES_READY" = "True" ]; then - echo -e "${GREEN}✓ PostgreSQL is ready${NC}" - kubectl get pods -n a2a-demo -l app=postgres -else - echo -e "${RED}✗ PostgreSQL is not ready (Ready: $POSTGRES_READY)${NC}" - kubectl get pods -n a2a-demo -l app=postgres -fi - -# Check Kafka -echo "" -echo "Checking Kafka..." -KAFKA_READY=$(kubectl get kafka a2a-kafka -n kafka -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null) -if [ "$KAFKA_READY" = "True" ]; then - echo -e "${GREEN}✓ Kafka is ready${NC}" - kubectl get kafka -n kafka -else - echo -e "${YELLOW}⚠ Kafka may not be fully ready (Status: $KAFKA_READY)${NC}" - kubectl get kafka -n kafka -fi - -# Check Agent pods -echo "" -echo "Checking A2A Agent pods..." -AGENT_PODS=$(kubectl get pods -n a2a-demo -l app=a2a-agent -o jsonpath='{.items | length}' 2>/dev/null) -AGENT_READY=$(kubectl get pods -n a2a-demo -l app=a2a-agent -o jsonpath='{range .items[*]}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}' 2>/dev/null | grep -c "True") - -echo "Total pods: $AGENT_PODS" -echo "Ready pods: $AGENT_READY" - -if [ "$AGENT_READY" -ge 2 ]; then - echo -e "${GREEN}✓ Agent pods are running${NC}" - kubectl get pods -n a2a-demo -l app=a2a-agent -o wide -else - echo -e "${YELLOW}⚠ Not all agent pods are ready${NC}" - kubectl get pods -n a2a-demo -l app=a2a-agent -o wide -fi - -# Check Agent service -echo "" -echo "Checking A2A Agent service..." -if kubectl get svc a2a-agent-service -n a2a-demo > /dev/null 2>&1; then - echo -e "${GREEN}✓ Agent service exists${NC}" - kubectl get svc a2a-agent-service -n a2a-demo -else - echo -e "${RED}✗ Agent service not found${NC}" -fi - -# Test agent endpoint -echo "" -echo "==========================================" -echo "To test the agent (via NodePort):" -echo "" -echo " curl http://localhost:8080/.well-known/agent-card.json" -echo "" -echo "To run the test client (demonstrating load balancing):" -echo " cd ../server" -echo " mvn test-compile exec:java -Dexec.classpathScope=test \\" -echo " -Dexec.mainClass=\"io.a2a.examples.cloud.A2ACloudExampleClient\" \\" -echo " -Dagent.url=\"http://localhost:8080\"" -echo "==========================================" diff --git a/examples/cloud-deployment/server/Dockerfile b/examples/cloud-deployment/server/Dockerfile deleted file mode 100644 index 25e1f593c..000000000 --- a/examples/cloud-deployment/server/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM registry.access.redhat.com/ubi9/openjdk-17:1.20 - -ENV LANGUAGE='en_US:en' - -# Labels for documentation and metadata -LABEL description="A2A Cloud Deployment Demo - Multi-pod agent with Kafka event replication" -LABEL version="1.0.0" - -# Copy the Quarkus application (fast-jar layout) -COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ -COPY --chown=185 target/quarkus-app/*.jar /deployments/ -COPY --chown=185 target/quarkus-app/app/ /deployments/app/ -COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ - -EXPOSE 8080 -USER 185 - -# Java options for Quarkus -ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" - -ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] diff --git a/examples/cloud-deployment/server/kill b/examples/cloud-deployment/server/kill deleted file mode 100644 index 543679eab..000000000 --- a/examples/cloud-deployment/server/kill +++ /dev/null @@ -1 +0,0 @@ -(eval):1: command not found: PF_PID= diff --git a/examples/cloud-deployment/server/pom.xml b/examples/cloud-deployment/server/pom.xml deleted file mode 100644 index a1e080420..000000000 --- a/examples/cloud-deployment/server/pom.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../../pom.xml - - - a2a-java-sdk-examples-cloud-deployment-server - - A2A Java SDK - Cloud Deployment Example Server - Example demonstrating A2A agent deployment in Kubernetes with database persistence and event replication - - - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - ${project.version} - - - - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - ${project.version} - - - - - io.github.a2asdk - a2a-java-extras-push-notification-config-store-database-jpa - ${project.version} - - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - ${project.version} - - - - - io.github.a2asdk - a2a-java-queue-manager-replication-mp-reactive - ${project.version} - - - - - io.quarkus - quarkus-messaging-kafka - - - - - io.quarkus - quarkus-jdbc-postgresql - - - - - io.quarkus - quarkus-hibernate-orm - - - - - io.quarkus - quarkus-smallrye-health - - - - io.github.a2asdk - a2a-java-sdk-client - test - - - - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - generate-code - generate-code-tests - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 17 - - - - - - - - native - - native - - - - diff --git a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java deleted file mode 100644 index b3adbcdd8..000000000 --- a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentCardProducer.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.a2a.examples.cloud; - - -import java.util.Collections; -import java.util.List; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; - -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import org.eclipse.microprofile.config.inject.ConfigProperty; - -/** - * Producer for the cloud deployment example agent card. - */ -@ApplicationScoped -public class CloudAgentCardProducer { - - @Inject - @ConfigProperty(name = "agent.url", defaultValue = "http://localhost:8080") - String agentUrl; - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return AgentCard.builder() - .name("Cloud Deployment Demo Agent") - .description("Demonstrates A2A multi-pod deployment with Kafka event replication, " + - "PostgreSQL persistence, and round-robin load balancing across Kubernetes pods") - .supportedInterfaces(Collections.singletonList( - new AgentInterface("JSONRPC", agentUrl))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList( - AgentSkill.builder() - .id("multi_pod_demo") - .name("Multi-Pod Replication Demo") - .description("Demonstrates cross-pod event replication. " + - "Send 'start' to initialize, 'process' to add artifacts, " + - "'complete' to finalize. Each artifact shows which pod processed it.") - .tags(List.of("demo", "cloud", "kubernetes", "replication")) - .examples(List.of( - "start", - "process", - "complete" - )) - .build() - )) - .build(); - } -} diff --git a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java deleted file mode 100644 index 976826fb3..000000000 --- a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java +++ /dev/null @@ -1,130 +0,0 @@ -package io.a2a.examples.cloud; - -import java.util.List; - -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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.InternalError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Producer for the cloud deployment example agent executor. - */ -@ApplicationScoped -public class CloudAgentExecutorProducer { - - private static final Logger LOGGER = LoggerFactory.getLogger(CloudAgentExecutorProducer.class); - - @Produces - public AgentExecutor agentExecutor() { - return new CloudAgentExecutor(); - } - - /** - * Modernized agent executor demonstrating multi-pod deployment with event replication. - * - * Message Protocol: - * - "start": Initialize task (SUBMITTED → WORKING), adds "Started by {pod-name}" - * - "process": Add artifact "Processed by {pod-name}" (fire-and-forget, stays WORKING) - * - "complete": Add artifact "Completed by {pod-name}" and transition to COMPLETED - * - * This demonstrates: - * - Cross-pod event replication via Kafka - * - Fire-and-forget pattern with controlled completion - * - Round-robin load balancing across pods - */ - private static class CloudAgentExecutor implements AgentExecutor { - - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - - try { - // Extract user message and normalize - String messageText = extractTextFromMessage(context.getMessage()).trim().toLowerCase(); - LOGGER.info("Received message: '{}'", messageText); - - // Get pod name from environment (set by Kubernetes Downward API) - String podName = System.getenv("POD_NAME"); - if (podName == null || podName.isEmpty()) { - podName = "unknown-pod"; - } - LOGGER.info("Processing on pod: {}", podName); - - // Simulate some processing time to make cross-pod behavior more visible - try { - Thread.sleep(500); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new InternalError("Processing interrupted"); - } - - // Handle message based on command - if ("complete".equals(messageText)) { - // Completion trigger - add final artifact and complete - LOGGER.info("Completion requested on pod: {}", podName); - String artifactText = "Completed by " + podName; - List> parts = List.of(new TextPart(artifactText)); - agentEmitter.addArtifact(parts); - agentEmitter.complete(); - LOGGER.info("Task completed on pod: {}", podName); - - } else if (context.getTask() == null) { - // Initial message - create task in SUBMITTED → WORKING state - LOGGER.info("Creating new task on pod: {}", podName); - agentEmitter.submit(); - agentEmitter.startWork(); - String artifactText = "Started by " + podName; - List> parts = List.of(new TextPart(artifactText)); - agentEmitter.addArtifact(parts); - LOGGER.info("Task created and started on pod: {}", podName); - - } else { - // Subsequent messages - add artifacts (fire-and-forget, stays in WORKING) - LOGGER.info("Adding artifact on pod: {}", podName); - String artifactText = "Processed by " + podName; - List> parts = List.of(new TextPart(artifactText)); - agentEmitter.addArtifact(parts); - // No state change - task remains in WORKING - LOGGER.info("Artifact added on pod: {}", podName); - } - - } catch (A2AError e) { - LOGGER.error("JSONRPC error processing task", e); - throw e; - } catch (Exception e) { - LOGGER.error("Error processing task", e); - throw new InternalError("Processing failed: " + e.getMessage()); - } - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - LOGGER.info("Task cancellation requested"); - agentEmitter.cancel(); - } - - /** - * Extracts text content from a message. - */ - private String extractTextFromMessage(Message message) { - StringBuilder textBuilder = new StringBuilder(); - if (message.parts() != null) { - for (Part part : message.parts()) { - if (part instanceof TextPart textPart) { - textBuilder.append(textPart.text()); - } - } - } - return textBuilder.toString(); - } - } -} diff --git a/examples/cloud-deployment/server/src/main/resources/META-INF/beans.xml b/examples/cloud-deployment/server/src/main/resources/META-INF/beans.xml deleted file mode 100644 index f8e1779ce..000000000 --- a/examples/cloud-deployment/server/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/examples/cloud-deployment/server/src/main/resources/application.properties b/examples/cloud-deployment/server/src/main/resources/application.properties deleted file mode 100644 index 653c36398..000000000 --- a/examples/cloud-deployment/server/src/main/resources/application.properties +++ /dev/null @@ -1,50 +0,0 @@ -# Agent Configuration -agent.url=${AGENT_URL:http://localhost:8080} - -# HTTP Server -quarkus.http.port=8080 -quarkus.http.host=0.0.0.0 - -# Database Configuration (PostgreSQL) -quarkus.datasource.db-kind=postgresql -quarkus.datasource.jdbc.url=${DATABASE_URL:jdbc:postgresql://localhost:5432/a2a} -quarkus.datasource.username=${DATABASE_USER:a2a} -quarkus.datasource.password=${DATABASE_PASSWORD:a2a} -quarkus.datasource.jdbc.max-size=16 - -# Hibernate ORM - Configure persistence unit "a2a-java" -quarkus.hibernate-orm."a2a-java".datasource= -quarkus.hibernate-orm."a2a-java".database.generation=update -quarkus.hibernate-orm."a2a-java".log.sql=false -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa,io.a2a.extras.pushnotificationconfigstore.database.jpa - -# Kafka Configuration for Event Replication -kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092} - -# MicroProfile Reactive Messaging - Outgoing (Publish to Kafka) -mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka -mp.messaging.outgoing.replicated-events-out.topic=a2a-replicated-events -mp.messaging.outgoing.replicated-events-out.value.serializer=org.apache.kafka.common.serialization.StringSerializer - -# MicroProfile Reactive Messaging - Incoming (Subscribe from Kafka) -mp.messaging.incoming.replicated-events-in.connector=smallrye-kafka -mp.messaging.incoming.replicated-events-in.topic=a2a-replicated-events -# Each pod needs a unique consumer group to receive ALL events (broadcast behavior) -# Using POD_NAME from Kubernetes Downward API ensures each instance gets its own group -mp.messaging.incoming.replicated-events-in.group.id=a2a-cloud-${POD_NAME:local} -mp.messaging.incoming.replicated-events-in.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer -mp.messaging.incoming.replicated-events-in.auto.offset.reset=earliest - -# Logging -# Default to INFO level for production-like behavior -# To enable DEBUG logging for troubleshooting, set these to DEBUG: -# quarkus.log.category."io.a2a.examples.cloud".level=DEBUG -# quarkus.log.category."io.a2a.server.events".level=DEBUG -# quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -# quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.level=INFO -quarkus.log.category."io.a2a".level=INFO -quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n - -# Health checks -quarkus.smallrye-health.root-path=/health diff --git a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java b/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java deleted file mode 100644 index 871affb4e..000000000 --- a/examples/cloud-deployment/server/src/test/java/io/a2a/examples/cloud/A2ACloudExampleClient.java +++ /dev/null @@ -1,443 +0,0 @@ -package io.a2a.examples.cloud; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.MessageEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; - -/** - * Test client demonstrating multi-pod A2A agent deployment with modernized message protocol. - *

- * This client: - * 1. Sends "start" to create task in SUBMITTED → WORKING state - * 2. Creates subscription to receive streaming updates - * 3. Sends multiple "process" messages that add artifacts showing which pod processed each - * 4. Verifies that at least 2 different pods handled requests (proving load balancing) - * 5. Sends "complete" to finalize task and close stream - *

- * Message Protocol: - * - "start": Initialize task (SUBMITTED → WORKING), adds "Started by {pod-name}" - * - "process": Add artifact "Processed by {pod-name}" (fire-and-forget, stays WORKING) - * - "complete": Add artifact "Completed by {pod-name}" and transition to COMPLETED - *

- * Usage: Run after deploying the agent to Kubernetes and setting up port-forward: - * kubectl port-forward -n a2a-demo svc/a2a-agent-service 8080:8080 - */ -public class A2ACloudExampleClient { - - private static final String AGENT_URL = System.getProperty("agent.url", "http://localhost:8080"); - private static final int PROCESS_MESSAGE_COUNT = Integer.parseInt(System.getProperty("process.message.count", "8")); // Number of "process" messages to send - private static final int MESSAGE_INTERVAL_MS = Integer.parseInt(System.getProperty("message.interval.ms", "1500")); - private static final boolean CI_MODE = Boolean.parseBoolean(System.getProperty("ci.mode", "false")); // Early exit when 2 pods observed - private static final int MAX_MESSAGES_UNTIL_TWO_PODS = Integer.parseInt(System.getProperty("max.messages.until.two.pods", "20")); // Max messages before giving up - private static final int MIN_PODS_TO_OBSERVE = 2; - - // Test state - private final Map observedPods = Collections.synchronizedMap(new HashMap<>()); - private final AtomicInteger artifactCount = new AtomicInteger(0); - private final AtomicBoolean testFailed = new AtomicBoolean(false); - private final CountDownLatch taskCreationLatch = new CountDownLatch(1); - private final CountDownLatch completionLatch = new CountDownLatch(1); - private String serverTaskId; - - // Clients - private Client streamingClient; - private Client nonStreamingClient; - private ClientConfig nonStreamingConfig; - - private AgentCard agentCard; - - public static void main(String[] args) throws Exception { - new A2ACloudExampleClient().run(); - } - - private void run() throws Exception { - printHeader(); - - agentCard = fetchAndConfigureAgentCard(); - String clientTaskId = generateClientTaskId(); - - createClients(agentCard); - - sendStartMessage(clientTaskId); - subscribeToTaskUpdates(); - sendProcessMessages(); - sendCompleteMessage(); - - waitForCompletion(); - printResults(); - } - - private void printHeader() { - System.out.println("============================================="); - System.out.println("A2A Cloud Deployment Example Client"); - System.out.println("============================================="); - System.out.println(); - System.out.println("Agent URL: " + AGENT_URL); - System.out.println("Process messages: " + PROCESS_MESSAGE_COUNT); - System.out.println("Message interval: " + MESSAGE_INTERVAL_MS + "ms"); - System.out.println(); - } - - private AgentCard fetchAndConfigureAgentCard() { - System.out.println("Fetching agent card..."); - AgentCard fetchedCard = A2A.getAgentCard(AGENT_URL); - System.out.println("✓ Agent: " + fetchedCard.name()); - System.out.println("✓ Description: " + fetchedCard.description()); - - // Override agent card URL to use the port-forwarded URL instead of internal K8s service URL - AgentCard agentCard = AgentCard.builder(fetchedCard) - .supportedInterfaces( - Collections.singletonList( - // Use localhost URL for port-forwarded connection - new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_URL))) - .build(); - System.out.println(); - return agentCard; - } - - private String generateClientTaskId() { - String clientTaskId = "cloud-test-" + System.currentTimeMillis(); - System.out.println("Client task ID: " + clientTaskId); - System.out.println(); - return clientTaskId; - } - - private void createClients(AgentCard agentCard) { - System.out.println("Creating streaming client for subscription..."); - ClientConfig streamingConfig = new ClientConfig.Builder() - .setStreaming(true) - .build(); - - streamingClient = Client.builder(agentCard) - .clientConfig(streamingConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - - System.out.println("Creating non-streaming client for sending messages..."); - nonStreamingConfig = new ClientConfig.Builder() - .setStreaming(false) - .build(); - - nonStreamingClient = Client.builder(agentCard) - .clientConfig(nonStreamingConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - - System.out.println("✓ Clients created"); - System.out.println(); - } - - private void sendStartMessage(String clientTaskId) { - System.out.println("Step 1: Sending 'start' to create task..."); - Message startMessage = A2A.toUserMessage("start", clientTaskId); - - try { - nonStreamingClient.sendMessage(startMessage, List.of((ClientEvent event, AgentCard card) -> { - if (event instanceof TaskEvent te) { - serverTaskId = te.getTask().id(); - System.out.println("✓ Task created: " + serverTaskId); - System.out.println(" State: " + te.getTask().status().state()); - taskCreationLatch.countDown(); - } - }), error -> { - System.err.println("✗ Failed to create task: " + error.getMessage()); - testFailed.set(true); - taskCreationLatch.countDown(); - }); - - // Wait for task creation to complete (max 5 seconds) - if (!taskCreationLatch.await(5, TimeUnit.SECONDS)) { - System.err.println("✗ Timeout waiting for task creation"); - System.exit(1); - } - - if (serverTaskId == null) { - System.err.println("✗ Failed to get server task ID"); - System.exit(1); - } - } catch (Exception e) { - System.err.println("✗ Failed to create task: " + e.getMessage()); - System.exit(1); - } - } - - private void subscribeToTaskUpdates() { - System.out.println(); - System.out.println("Step 2: Subscribing to task for streaming updates..."); - - AtomicBoolean subscribed = new AtomicBoolean(false); - int maxRetries = 3; - - for (int attempt = 1; attempt <= maxRetries; attempt++) { - try { - if (attempt > 1) { - System.out.println("Retry attempt " + attempt + "/" + maxRetries + "..."); - Thread.sleep(1000); // Wait for Kafka events to propagate - } - - streamingClient.subscribeToTask( - new TaskIdParams(serverTaskId), - List.of(this::handleSubscriptionEvent), - this::handleSubscriptionError - ); - - System.out.println("✓ Subscribed to task updates"); - subscribed.set(true); - break; - } catch (Exception e) { - if (attempt < maxRetries) { - System.out.println("⚠ Failed to subscribe (attempt " + attempt + "/" + maxRetries + "): " + e.getMessage()); - } else { - System.err.println("✗ Failed to subscribe after " + maxRetries + " attempts: " + e.getMessage()); - System.exit(1); - } - } - } - - if (!subscribed.get()) { - System.err.println("✗ Failed to establish subscription"); - System.exit(1); - } - } - - private void handleSubscriptionEvent(ClientEvent event, AgentCard card) { - if (event instanceof TaskUpdateEvent tue) { - if (tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifactEvent) { - int count = artifactCount.incrementAndGet(); - String artifactText = extractTextFromArtifact(artifactEvent); - System.out.println(" Artifact #" + count + ": " + artifactText); - - // Extract pod name from artifact text - String podName = extractPodName(artifactText); - if (podName != null && !podName.equals("unknown-pod")) { - int invokeCount = observedPods.getOrDefault(podName, 0); - observedPods.put(podName, ++invokeCount); - System.out.println(" → Pod: " + podName + " (Total unique pods: " + observedPods.size() + ")"); - } - } - } else if (event instanceof TaskEvent te) { - // Check for task completion - if (te.getTask().status().state().isFinal()) { - System.out.println(" Task reached final state: " + te.getTask().status().state()); - completionLatch.countDown(); - } - } - } - - private void handleSubscriptionError(Throwable error) { - // Filter out normal stream closure errors (expected when task completes) - if (!isStreamClosedError(error)) { - System.err.println("✗ Subscription error: " + error.getMessage()); - testFailed.set(true); - } else { - System.out.println("ℹ Subscription stream closed (expected after task completion)"); - } - } - - private void sendProcessMessages() throws InterruptedException { - System.out.println(); - if (CI_MODE) { - System.out.println("Step 3: Sending 'process' messages until 2 pods observed (CI mode, max: " + MAX_MESSAGES_UNTIL_TWO_PODS + ", interval: " + MESSAGE_INTERVAL_MS + "ms)..."); - } else { - System.out.println("Step 3: Sending " + PROCESS_MESSAGE_COUNT + " 'process' messages (interval: " + MESSAGE_INTERVAL_MS + "ms)..."); - } - System.out.println("--------------------------------------------"); - - int messageCount = 0; - int maxMessages = CI_MODE ? MAX_MESSAGES_UNTIL_TWO_PODS : PROCESS_MESSAGE_COUNT; - - while (messageCount < maxMessages) { - messageCount++; - final int messageNum = messageCount; - - // Create a new client for each request to force new HTTP connection - Client freshClient = Client.builder(agentCard) - .clientConfig(nonStreamingConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(new TextPart("process")) - .taskId(serverTaskId) - .build(); - - try { - freshClient.sendMessage(message, List.of((ClientEvent event, AgentCard card) -> { - if (event instanceof MessageEvent || event instanceof TaskEvent) { - System.out.println("✓ Process message " + messageNum + " sent"); - } - }), error -> { - System.err.println("✗ Process message " + messageNum + " failed: " + error.getMessage()); - testFailed.set(true); - }); - - Thread.sleep(MESSAGE_INTERVAL_MS); - - // In CI mode, check if we've observed 2 pods and can exit early - if (CI_MODE && observedPods.size() >= 2) { - System.out.println(); - System.out.println("✓ CI mode: Successfully observed 2 pods after " + messageNum + " messages. Stopping early."); - break; - } - } catch (Exception e) { - System.err.println("✗ Failed to send process message " + messageNum + ": " + e.getMessage()); - testFailed.set(true); - } - } - - // Wait for process artifacts to arrive via subscription - System.out.println(); - System.out.println("Waiting for process artifacts to arrive..."); - Thread.sleep(2000); - } - - private void sendCompleteMessage() { - System.out.println(); - System.out.println("Step 4: Sending 'complete' to finalize task..."); - - Client completeClient = Client.builder(agentCard) - .clientConfig(nonStreamingConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - - Message completeMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(new TextPart("complete")) - .taskId(serverTaskId) - .build(); - - try { - completeClient.sendMessage(completeMessage, List.of((ClientEvent event, AgentCard card) -> { - if (event instanceof TaskEvent te) { - System.out.println("✓ Complete message sent, task state: " + te.getTask().status().state()); - } - }), error -> { - System.err.println("✗ Failed to send complete message: " + error.getMessage()); - testFailed.set(true); - }); - } catch (Exception e) { - System.err.println("✗ Failed to send complete message: " + e.getMessage()); - testFailed.set(true); - } - } - - private void waitForCompletion() throws InterruptedException { - System.out.println(); - System.out.println("Waiting for task to complete..."); - if (!completionLatch.await(10, TimeUnit.SECONDS)) { - System.err.println("⚠ Timeout waiting for task completion"); - } - } - - private void printResults() { - System.out.println(); - System.out.println("============================================="); - System.out.println("Test Results"); - System.out.println("============================================="); - System.out.println("Total artifacts received: " + artifactCount.get()); - System.out.println("Unique pods observed: " + observedPods.size()); - System.out.println("Pod names and counts: " + observedPods); - System.out.println(); - - if (testFailed.get()) { - System.out.println("✗ TEST FAILED - Errors occurred during execution"); - System.exit(1); - } else if (observedPods.size() < MIN_PODS_TO_OBSERVE) { - System.out.printf("✗ TEST FAILED - Expected at least %d different pods, but only saw: %d\n", MIN_PODS_TO_OBSERVE, observedPods.size()); - System.out.println(" This suggests load balancing is not working correctly."); - System.exit(1); - } else { - System.out.println("✓ TEST PASSED - Successfully demonstrated multi-pod processing!"); - System.out.println(" Messages were handled by " + observedPods.size() + " different pods."); - System.out.println(" This proves that:"); - System.out.println(" - Load balancing is working (round-robin across pods)"); - System.out.println(" - Event replication is working (subscriber sees events from all pods)"); - System.out.println(" - Database persistence is working (task state shared across pods)"); - System.exit(0); - } - } - - private static String extractTextFromArtifact(TaskArtifactUpdateEvent event) { - StringBuilder text = new StringBuilder(); - if (event.artifact() != null) { - for (Part part : event.artifact().parts()) { - if (part instanceof TextPart textPart) { - text.append(textPart.text()); - } - } - } - return text.toString(); - } - - private static String extractPodName(String artifactText) { - // Artifact text format: "Started by " or "Processed by " or "Completed by " - if (artifactText != null) { - if (artifactText.startsWith("Started by ")) { - return artifactText.substring("Started by ".length()).trim(); - } else if (artifactText.startsWith("Processed by ")) { - return artifactText.substring("Processed by ".length()).trim(); - } else if (artifactText.startsWith("Completed by ")) { - return artifactText.substring("Completed by ".length()).trim(); - } - } - return null; - } - - /** - * Checks if the error is a normal stream closure error that should be ignored. - * HTTP/2 stream cancellation and closure are expected when task completes and queue closes. - * Based on MultiInstanceReplicationTest.isStreamClosedError(). - */ - private static boolean isStreamClosedError(Throwable error) { - if (error == null) { - return false; - } - - // Check for IOException which includes stream cancellation - if (error instanceof IOException) { - String message = error.getMessage(); - if (message != null) { - // Filter out normal stream closure/cancellation errors - if (message.contains("Stream closed") || - message.contains("Stream") && message.contains("cancelled") || - message.contains("EOF reached") || - message.contains("CANCEL")) { - return true; - } - } - } - - // Check cause recursively - Throwable cause = error.getCause(); - if (cause != null && cause != error) { - return isStreamClosedError(cause); - } - - return false; - } -} diff --git a/examples/helloworld/client/README.md b/examples/helloworld/client/README.md deleted file mode 100644 index cd5043f11..000000000 --- a/examples/helloworld/client/README.md +++ /dev/null @@ -1,261 +0,0 @@ -# A2A Hello World Example - -This example demonstrates how to use the A2A Java SDK to communicate with an A2A server. The example includes a Java client that sends both regular and streaming messages to a Python A2A server. - -## Prerequisites - -- Java 11 or higher -- [JBang](https://www.jbang.dev/documentation/guide/latest/installation.html) (see [INSTALL_JBANG.md](INSTALL_JBANG.md) for quick installation instructions) -- Python 3.8 or higher -- [uv](https://github.com/astral-sh/uv) (recommended) or pip -- Git - -## Setup and Run the Python A2A Server - -The Python A2A server is part of the [a2a-samples](https://github.com/google-a2a/a2a-samples) project. To set it up and run it: - -1. Clone the a2a-samples repository: - ```bash - git clone https://github.com/google-a2a/a2a-samples.git - cd a2a-samples/samples/python/agents/helloworld - ``` - -2. **Recommended method**: Install dependencies using uv (much faster Python package installer): - ```bash - # Install uv if you don't have it already - # On macOS and Linux - curl -LsSf https://astral.sh/uv/install.sh | sh - # On Windows - powershell -c "irm https://astral.sh/uv/install.ps1 | iex" - - # Install the package using uv - uv venv - source .venv/bin/activate # On Windows: .venv\Scripts\activate - uv pip install -e . - ``` - -4. Run the server with uv (recommended): - ```bash - uv run . - ``` - -The server will start running on `http://localhost:9999`. - -### Using the Java Server Instead - -Alternatively, you can use the Java server example instead of the Python server. The Java server supports multiple transport protocols (JSONRPC, GRPC, and HTTP+JSON). See the [server README](../server/README.md) for details on starting the Java server with different transport protocols. - -## Run the Java A2A Client - -The Java client can be run using either Maven or JBang. - -### Build the A2A Java SDK - -First, ensure you have built the `a2a-java` project: - -```bash -cd /path/to/a2a-java -mvn clean install -``` - -### Option 1: Using Maven (Recommended) - -Run the client using Maven's exec plugin: - -```bash -cd examples/helloworld/client -mvn exec:java -``` - -#### Transport Protocol Selection - -The client supports multiple transport protocols. You can select which protocol to use via the `quarkus.agentcard.protocol` property: - -**Using JSONRPC (default)**: -```bash -mvn exec:java -``` - -**Using GRPC**: -```bash -mvn exec:java -Dquarkus.agentcard.protocol=GRPC -``` - -**Using HTTP+JSON**: -```bash -mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -``` - -Available protocols: -- `JSONRPC` - Uses JSON-RPC for communication (default) -- `GRPC` - Uses gRPC for communication -- `HTTP+JSON` - Uses HTTP with JSON payloads - -**Note**: The protocol you select on the client must match the protocol configured on the server. - -#### Enabling OpenTelemetry - -To enable OpenTelemetry with Maven: -```bash -mvn exec:java -Dopentelemetry=true -``` - -You can combine protocol selection with OpenTelemetry: -```bash -mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true -``` - -### Option 2: Using JBang - -A JBang script is provided for running the client without Maven: - -1. Make sure you have JBang installed. If not, follow the [JBang installation guide](https://www.jbang.dev/documentation/guide/latest/installation.html). - -3. Run the client using the JBang script: - ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java - ``` - -#### Transport Protocol Selection with JBang - -Select the transport protocol using the same `-Dquarkus.agentcard.protocol` property: - -**Using JSONRPC (default)**: -```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -``` - -**Using GRPC**: -```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC -``` - -**Using HTTP+JSON**: -```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON -``` - -#### Enabling OpenTelemetry with JBang - -To enable OpenTelemetry with JBang: -```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true -``` - -You can combine protocol selection with OpenTelemetry: -```bash -jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=GRPC -Dopentelemetry=true -``` - -## What the Example Does - -The Java client (`HelloWorldClient.java`) performs the following actions: - -1. Fetches the server's public agent card -2. Fetches the server's extended agent card -3. Creates a client using the extended agent card that connects to the Python server at `http://localhost:9999`. -4. Sends a regular message asking "how much is 10 USD in INR?". -5. Prints the server's response. -6. Sends the same message as a streaming request. -7. Prints each chunk of the server's streaming response as it arrives. - -## Enable OpenTelemetry (Optional) - -The client includes support for distributed tracing with OpenTelemetry. To enable it: - -### Prerequisites - -**IMPORTANT**: The client expects an OpenTelemetry collector to be ready and accepting traces. You have two options: - -#### Option 1: Use the Java Server Example (Recommended) - -Instead of the Python server, use the Java server example which has built-in OpenTelemetry support: - -1. **Start the Java server with OpenTelemetry enabled**: - ```bash - mvn quarkus:dev -Popentelemetry -pl examples/helloworld/server/ -Dquarkus.agentcard.protocol=HTTP+JSON - ``` - This will: - - Start the server at `http://localhost:9999` - - Launch Grafana at `http://localhost:3001` - - Start OTLP collectors on ports 5317 (gRPC) and 5318 (HTTP) - -2. **Run the client with OpenTelemetry**: - - Using Maven (from `examples/helloworld/client`): - ```bash - mvn exec:java -Dopentelemetry=true - ``` - - With specific protocol: - ```bash - mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true - ``` - - Or using JBang: - ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true - ``` - - With specific protocol: - ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true - ``` - -3. **View traces in Grafana**: - - Open `http://localhost:3001` (credentials: admin/admin) - - Go to "Explore" → select "Tempo" data source - - View distributed traces showing the full request flow from client to server - -#### Option 2: Use External OpenTelemetry Collector - -If you want to use the Python server with OpenTelemetry: - -1. **Start an OpenTelemetry collector** on port 5317 (e.g., using Docker): - ```bash - docker run -p 5317:4317 otel/opentelemetry-collector - ``` - -2. **Run the Python server** - -3. **Run the client with OpenTelemetry**: - ```bash - mvn exec:java -Dopentelemetry=true - ``` - - Or with JBang: - ```bash - jbang examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java -Dopentelemetry=true - ``` - - With specific protocol: - ```bash - mvn exec:java -Dquarkus.agentcard.protocol=HTTP+JSON -Dopentelemetry=true - ``` - -### What Gets Traced - -When OpenTelemetry is enabled, the client traces: -- Agent card fetching (public and extended) -- Message sending (blocking and streaming) -- Task operations (get, cancel, list) -- Push notification configuration operations -- Connection and transport layer operations - -Client traces are automatically linked with server traces (when using the Java server), providing end-to-end visibility of the entire A2A protocol flow. - -### Configuration - -The client is configured to send traces to `http://localhost:5317` (OTLP gRPC endpoint). To use a different endpoint, modify the `initOpenTelemetry()` method in `HelloWorldClient.java`: - -```java -OtlpGrpcSpanExporter.builder() - .setEndpoint("http://your-collector:4317") - .build() -``` - -## Notes - -- Make sure the Python server is running before starting the Java client. -- The client will wait for 10 seconds to collect streaming responses before exiting. -- You can modify the message text or server URL in the `HelloWorldClient.java` file if needed. diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml deleted file mode 100644 index 73932409c..000000000 --- a/examples/helloworld/client/pom.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-examples-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-java-sdk-examples-client - - Java SDK A2A Examples - HelloWorld Client - Examples for the Java SDK for the Agent2Agent Protocol (A2A) - - - src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java - - - - - io.github.a2asdk - a2a-java-sdk-client - - - io.github.a2asdk - a2a-java-sdk-jsonrpc-common - - - io.github.a2asdk - a2a-java-sdk-client-transport-grpc - - - io.github.a2asdk - a2a-java-sdk-client-transport-rest - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-client - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-client-propagation - - - io.opentelemetry - opentelemetry-sdk - - - io.opentelemetry - opentelemetry-exporter-otlp - - - io.opentelemetry - opentelemetry-exporter-logging - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.codehaus.gmavenplus - gmavenplus-plugin - - - validate-jbang-versions - validate - - execute - - - - - - - - - - - org.codehaus.mojo - exec-maven-plugin - 3.6.2 - - io.a2a.examples.helloworld.HelloWorldClient - - - opentelemetry - ${opentelemetry} - - - - - - - \ No newline at end of file diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java deleted file mode 100644 index 6634898c7..000000000 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java +++ /dev/null @@ -1,193 +0,0 @@ -package io.a2a.examples.helloworld; - -import static io.a2a.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper.OTEL_TRACER_KEY; -import static io.a2a.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper.OTEL_OPEN_TELEMETRY_KEY; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import io.a2a.A2A; - -import io.a2a.client.Client; -import io.a2a.client.ClientBuilder; -import io.a2a.client.ClientEvent; -import io.a2a.client.MessageEvent; -import io.a2a.client.http.A2ACardResolver; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfig; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import io.grpc.Channel; -import io.grpc.ManagedChannelBuilder; -import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; -import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; -import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; -import java.util.function.Function; - -/** - * A simple example of using the A2A Java SDK to communicate with an A2A server. - * This example is equivalent to the Python example provided in the A2A Python SDK. - */ -public class HelloWorldClient { - - private static final String SERVER_URL = "http://localhost:9999"; - private static final String MESSAGE_TEXT = "how much is 10 USD in INR?"; - - public static void main(String[] args) { - OpenTelemetrySdk openTelemetrySdk = null; - try { - AgentCard publicAgentCard = new A2ACardResolver(SERVER_URL).getAgentCard(); - System.out.println("Successfully fetched public agent card:"); - System.out.println(JsonUtil.toJson(publicAgentCard)); - System.out.println("Using public agent card for client initialization (default)."); - AgentCard finalAgentCard = publicAgentCard; - - if (publicAgentCard.capabilities().extendedAgentCard()) { - System.out.println("Public card supports authenticated extended card. Attempting to fetch from: " + SERVER_URL + "/ExtendedAgentCard"); - Map authHeaders = new HashMap<>(); - authHeaders.put("Authorization", "Bearer dummy-token-for-extended-card"); - AgentCard extendedAgentCard = A2A.getAgentCard(SERVER_URL, "/ExtendedAgentCard", authHeaders); - System.out.println("Successfully fetched authenticated extended agent card:"); - System.out.println(JsonUtil.toJson(extendedAgentCard)); - System.out.println("Using AUTHENTICATED EXTENDED agent card for client initialization."); - finalAgentCard = extendedAgentCard; - } else { - System.out.println("Public card does not indicate support for an extended card. Using public card."); - } - - final CompletableFuture messageResponse = new CompletableFuture<>(); - - // Create consumers list for handling client events - List> consumers = new ArrayList<>(); - consumers.add((event, agentCard) -> { - if (event instanceof MessageEvent messageEvent) { - Message responseMessage = messageEvent.getMessage(); - StringBuilder textBuilder = new StringBuilder(); - if (responseMessage.parts() != null) { - for (Part part : responseMessage.parts()) { - if (part instanceof TextPart textPart) { - textBuilder.append(textPart.text()); - } - } - } - messageResponse.complete(textBuilder.toString()); - } else { - System.out.println("Received client event: " + event.getClass().getSimpleName()); - } - }); - - // Create error handler for streaming errors - Consumer streamingErrorHandler = (error) -> { - System.err.println("Streaming error occurred: " + error.getMessage()); - error.printStackTrace(); - messageResponse.completeExceptionally(error); - }; - - if (Boolean.getBoolean("opentelemetry")) { - openTelemetrySdk = initOpenTelemetry(); - } - - ClientBuilder clientBuilder = Client - .builder(finalAgentCard) - .addConsumers(consumers) - .streamingErrorHandler(streamingErrorHandler); - configureTransport(clientBuilder, openTelemetrySdk); - Client client = clientBuilder.build(); - - Message message = A2A.toUserMessage(MESSAGE_TEXT); // the message ID will be automatically generated for you - try { - System.out.println("Sending message: " + MESSAGE_TEXT); - client.sendMessage(message); - System.out.println("Message sent successfully. Responses will be handled by the configured consumers."); - - String responseText = messageResponse.get(); - System.out.println("Response: " + responseText); - } catch (Exception e) { - System.err.println("Failed to get response: " + e.getMessage()); - } - } catch (Exception e) { - System.err.println("An error occurred: " + e.getMessage()); - e.printStackTrace(); - } finally { - // Ensure OpenTelemetry SDK is properly shut down to export all pending spans - if (openTelemetrySdk != null) { - System.out.println("Shutting down OpenTelemetry SDK..."); - openTelemetrySdk.close(); - System.out.println("OpenTelemetry SDK shutdown complete."); - } - } - } - - static OpenTelemetrySdk initOpenTelemetry() { - SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() - .addSpanProcessor(BatchSpanProcessor.builder( - OtlpGrpcSpanExporter.builder() - .setEndpoint("http://localhost:5317") - .build() - ).build()) - .setResource(Resource.getDefault().toBuilder() - .put("service.version", "1.0") - .put("service.name", "helloworld-client") - .build()) - .build(); - - return OpenTelemetrySdk.builder() - .setTracerProvider(sdkTracerProvider) - .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) - .build(); - } - private static void configureTransport(ClientBuilder clientBuilder, OpenTelemetrySdk openTelemetrySdk) { - ClientTransportConfig transportConfig; - switch(System.getProperty("quarkus.agentcard.protocol", "JSONRPC")) { - case "GRPC": - Function channelFactory = url -> { - // Extract "localhost:9999" from "http://localhost:9999" - String target = url.replaceAll("^https?://", ""); - return ManagedChannelBuilder.forTarget(target) - .usePlaintext() // No TLS - .build(); - }; - transportConfig = new GrpcTransportConfigBuilder().channelFactory(channelFactory).build(); - updateTransportConfig(transportConfig, openTelemetrySdk); - clientBuilder.withTransport(GrpcTransport.class, transportConfig); - break; - case "HTTP+JSON": - transportConfig = new RestTransportConfig(); - updateTransportConfig(transportConfig, openTelemetrySdk); - clientBuilder.withTransport(RestTransport.class, transportConfig); - break; - case "JSONRPC": - default: - transportConfig = new JSONRPCTransportConfig(); - updateTransportConfig(transportConfig, openTelemetrySdk); - clientBuilder.withTransport(JSONRPCTransport.class, transportConfig); - break; - } - } - - private static void updateTransportConfig(ClientTransportConfig transportConfig, OpenTelemetrySdk openTelemetrySdk) { - if (openTelemetrySdk != null) { - Map parameters = new HashMap<>(transportConfig.getParameters()); - parameters.put(OTEL_TRACER_KEY, openTelemetrySdk.getTracer("helloworld-client")); - parameters.put(OTEL_OPEN_TELEMETRY_KEY, openTelemetrySdk); - transportConfig.setParameters(parameters); - } - } -} diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java deleted file mode 100644 index 9616b8da6..000000000 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldRunner.java +++ /dev/null @@ -1,42 +0,0 @@ - -///usr/bin/env jbang "$0" "$@" ; exit $? - -//DEPS io.github.a2asdk:a2a-java-sdk-client:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-jsonrpc:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-grpc:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-client-transport-rest:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client:1.0.0.Alpha4-SNAPSHOT -//DEPS io.github.a2asdk:a2a-java-sdk-opentelemetry-client-propagation:1.0.0.Alpha4-SNAPSHOT -//DEPS io.opentelemetry:opentelemetry-sdk:1.55.0 -//DEPS io.opentelemetry:opentelemetry-exporter-otlp:1.55.0 -//DEPS io.opentelemetry:opentelemetry-exporter-logging:1.55.0 -//DEPS io.grpc:grpc-netty:1.77.0 -//SOURCES HelloWorldClient.java - -/** - * JBang script to run the A2A HelloWorldClient example. - * This script automatically handles the dependencies and runs the client. - * - * Prerequisites: - * - JBang installed (see https://www.jbang.dev/documentation/guide/latest/installation.html) - * - A running A2A server (see README.md for instructions on setting up the Python server) - * - * Usage: - * $ jbang HelloWorldRunner.java - * - * The script will communicate with the A2A server at http://localhost:9999 - */ -public class HelloWorldRunner { - - public static void main(String[] args) { - for (String arg : args) { - if (arg != null && arg.startsWith("-D")) { - int index = arg.indexOf('='); - if (index > 0) { - System.setProperty(arg.substring(2, index), arg.substring(index + 1)); - } - } - } - io.a2a.examples.helloworld.HelloWorldClient.main(args); - } -} diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/INSTALL_JBANG.md b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/INSTALL_JBANG.md deleted file mode 100644 index 7bfa392f6..000000000 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/INSTALL_JBANG.md +++ /dev/null @@ -1,56 +0,0 @@ -# Installing JBang - -[JBang](https://www.jbang.dev/) is a tool that makes it easy to run Java code with zero installation. This guide provides quick installation instructions for different platforms. - -## Linux and macOS - -You can install JBang using `curl` or `wget`: - -```bash -# Using curl -curl -Ls https://sh.jbang.dev | bash -s - app setup - -# OR using wget -wget -q https://sh.jbang.dev -O - | bash -s - app setup -``` - -After installation, you may need to restart your terminal or source your shell configuration file: - -```bash -source ~/.bashrc # For Bash -source ~/.zshrc # For Zsh -``` - -## Windows - -### Using PowerShell - -```powershell -iex "& { $(iwr https://ps.jbang.dev) } app setup" -``` - -### Using Chocolatey - -```powershell -choco install jbang -``` - -### Using Scoop - -```powershell -scoop install jbang -``` - -## Verifying Installation - -To verify that JBang is installed correctly, run: - -```bash -jbang --version -``` - -You should see the JBang version number displayed. - -## Further Information - -For more detailed installation instructions and options, visit the [JBang installation documentation](https://www.jbang.dev/documentation/guide/latest/installation.html). \ No newline at end of file diff --git a/examples/helloworld/pom.xml b/examples/helloworld/pom.xml deleted file mode 100644 index 4401ccbe6..000000000 --- a/examples/helloworld/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-sdk-examples-parent - pom - - Java SDK A2A Examples: Hello World - Examples for the Java SDK for the Agent2Agent Protocol (A2A) - - - - - io.quarkus - quarkus-bom - ${quarkus.platform.version} - pom - import - - - io.github.a2asdk - a2a-java-sdk-client - - - - - - client - server - - \ No newline at end of file diff --git a/examples/helloworld/server/README.md b/examples/helloworld/server/README.md deleted file mode 100644 index 66f39f7ec..000000000 --- a/examples/helloworld/server/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# A2A Hello World Example - -This example demonstrates how to use the A2A Java SDK to communicate with an A2A client. The example includes a Java server that receives both regular and streaming messages from a Python A2A client. - -## Prerequisites - -- Java 11 or higher -- Python 3.8 or higher -- [uv](https://github.com/astral-sh/uv) -- Git - -## Run the Java A2A Server - -The Java server can be started using `mvn` as follows: - -```bash -cd examples/helloworld/server -mvn quarkus:dev -``` - -### Transport Protocol Selection - -The server supports multiple transport protocols. You can select which protocol to use via the `quarkus.agentcard.protocol` property: - -**Using JSONRPC (default)**: -```bash -mvn quarkus:dev -``` - -**Using GRPC**: -```bash -mvn quarkus:dev -Dquarkus.agentcard.protocol=GRPC -``` - -**Using HTTP+JSON**: -```bash -mvn quarkus:dev -Dquarkus.agentcard.protocol=HTTP+JSON -``` - -You can also change the default protocol by editing `src/main/resources/application.properties` and setting: -```properties -quarkus.agentcard.protocol=HTTP+JSON -``` - -Available protocols: -- `JSONRPC` - Uses JSON-RPC for communication (default) -- `GRPC` - Uses gRPC for communication -- `HTTP+JSON` - Uses HTTP with JSON payloads - -## Setup and Run the Python A2A Client - -The Python A2A client is part of the [a2a-samples](https://github.com/google-a2a/a2a-samples) project. To set it up and run it: - -1. Clone the a2a-samples repository: - ```bash - git clone https://github.com/google-a2a/a2a-samples.git - cd a2a-samples/samples/python/agents/helloworld - ``` - -2. **Recommended method**: Install dependencies using uv (much faster Python package installer): - ```bash - # Install uv if you don't have it already - # On macOS and Linux - curl -LsSf https://astral.sh/uv/install.sh | sh - # On Windows - powershell -c "irm https://astral.sh/uv/install.ps1 | iex" - - # Install the package using uv - uv venv - source .venv/bin/activate # On Windows: .venv\Scripts\activate - uv pip install -e . - ``` - -4. Run the client with uv (recommended): - ```bash - uv run test_client.py - ``` - -The client will connect to the Java server running on `http://localhost:9999`. - -## What the Example Does - -The Python A2A client (`test_client.py`) performs the following actions: - -1. Fetches the server's public agent card -2. Fetches the server's extended agent card if supported by the server (see https://github.com/a2aproject/a2a-java/issues/81) -3. Creates an A2A client using the extended agent card that connects to the Python server at `http://localhost:9999`. -4. Sends a regular message asking "how much is 10 USD in INR?". -5. Prints the server's response. -6. Sends the same message as a streaming request. -7. Prints each chunk of the server's streaming response as it arrives. - -## Enable OpenTelemetry (Optional) - -The server includes support for distributed tracing with OpenTelemetry. To enable it: - -1. **Run with the OpenTelemetry profile**: - ```bash - mvn quarkus:dev -Popentelemetry - ``` - -2. **Access Grafana dashboard**: - - Quarkus Dev Services will automatically start a Grafana observability stack - - Open Grafana at `http://localhost:3001` (default credentials: admin/admin) - - View traces in the "Explore" section using the Tempo data source - -3. **What gets traced**: - - All A2A protocol operations (send message, get task, cancel task, etc.) - - Streaming message responses - - Task lifecycle events - - Custom operations in your `AgentExecutor` implementation (using `@Trace` annotation) - -4. **Configuration**: - - OpenTelemetry settings are in `application.properties` - - OTLP exporters run on ports 5317 (gRPC) and 5318 (HTTP) - - To use a custom OTLP endpoint, uncomment and modify: - ```properties - quarkus.otel.exporter.otlp.endpoint=http://localhost:4317 - ``` - -For more information, see the [OpenTelemetry extras module documentation](../../../extras/opentelemetry/README.md). - -## Notes - -- Make sure the Java server is running before starting the Python client. -- The client will wait for 10 seconds to collect streaming responses before exiting. -- You can modify the server's response in `AgentExecutorProducer.java` if needed. -- You can modify the server's agent card in `AgentCardProducer.java` if needed. -- You can modify the server's URL in `application.properties` and `AgentCardProducer.java` if needed. \ No newline at end of file diff --git a/examples/helloworld/server/pom.xml b/examples/helloworld/server/pom.xml deleted file mode 100644 index 381704fb9..000000000 --- a/examples/helloworld/server/pom.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-examples-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-java-sdk-examples-server - - Java SDK A2A Examples - HelloWorld Server - Examples for the Java SDK for the Agent2Agent Protocol (A2A) - - - - io.github.a2asdk - a2a-java-sdk-client - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - - io.quarkus - quarkus-resteasy - provided - - - io.github.a2asdk - a2a-java-sdk-reference-grpc - - - io.github.a2asdk - a2a-java-sdk-reference-rest - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - jakarta.ws.rs - jakarta.ws.rs-api - - - - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - generate-code - generate-code-tests - - - - - --add-opens=java.base/java.lang=ALL-UNNAMED - - - - - - - - opentelemetry - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-server - - - io.quarkus - quarkus-opentelemetry - - - io.quarkus - quarkus-observability-devservices-lgtm - provided - - - - - \ No newline at end of file diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java deleted file mode 100644 index 0f4821290..000000000 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentCardProducer.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.a2a.examples.helloworld; - - -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.AgentInterface; -import io.a2a.spec.AgentSkill; -import org.eclipse.microprofile.config.inject.ConfigProperty; - -@ApplicationScoped -public class AgentCardProducer { - - @ConfigProperty(name = "quarkus.agentcard.protocol", defaultValue="JSONRPC") - String protocol; - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - // NOTE: Transport validation will automatically check that transports specified - // in this AgentCard match those available on the classpath when handlers are initialized - - return AgentCard.builder() - .name("Hello World Agent") - .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList(getAgentInterface())) - .version("1.0.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(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(); - } - - private AgentInterface getAgentInterface() { - switch(protocol) { - case "GRPC": - return new AgentInterface("GRPC", "localhost:9000"); - case "HTTP+JSON": - return new AgentInterface("HTTP+JSON", "http://localhost:9999"); - case "JSONRPC": - default: - return new AgentInterface("JSONRPC", "http://localhost:9999"); - } - } -} diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java deleted file mode 100644 index 3c3be977b..000000000 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.a2a.examples.helloworld; - -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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.UnsupportedOperationError; - -@ApplicationScoped -public class AgentExecutorProducer { - - @Produces - public AgentExecutor agentExecutor() { - return new AgentExecutor() { - @Override - public void execute(RequestContext context, AgentEmitter emitter) throws A2AError { - emitter.sendMessage("Hello World"); - } - - @Override - public void cancel(RequestContext context, AgentEmitter emitter) throws A2AError { - throw new UnsupportedOperationError(); - } - }; - } -} diff --git a/examples/helloworld/server/src/main/resources/application.properties b/examples/helloworld/server/src/main/resources/application.properties deleted file mode 100644 index eb8aee9ba..000000000 --- a/examples/helloworld/server/src/main/resources/application.properties +++ /dev/null @@ -1,12 +0,0 @@ -%dev.quarkus.http.port=9999 - -# Protocol can be JSONRPC, GRPC, or HTTP+JSON -quarkus.agentcard.protocol=JSONRPC - -# OpenTelemetry configuration -quarkus.otel.sdk.disabled=false -quarkus.observability.lgtm.grafana-port=3001 -quarkus.observability.lgtm.otel-grpc-port=5317 -quarkus.observability.lgtm.otel-http-port=5318 -#quarkus.otel.exporter.otlp.endpoint=http://localhost:4317 -#quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{traceId}, parentId=%X{parentId}, spanId=%X{spanId}, sampled=%X{sampled} [%c{2.}] (%t) %s%e%n \ No newline at end of file diff --git a/extras/README.md b/extras/README.md deleted file mode 100644 index e3692e49e..000000000 --- a/extras/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# A2A Java SDK - Extras - -This directory contains additions to what is provided by the default SDK implementations. - -Please see the README's of each child directory for more details. - -## HTTP Client - -[`http-client-vertx`](./http-client-vertx/README.md) - Vert.x WebClient-based implementation of `A2AHttpClient` for reactive, high-performance HTTP communication. Replaces the default JDK HttpClient with a non-blocking, event-loop based client. Uses SPI for automatic discovery - simply add this library as a dependency to use it. Recommended for reactive applications, Quarkus, and high-throughput scenarios. - -## Storage & Persistence - -[`task-store-database-jpa`](./task-store-database-jpa/README.md) - Replaces the default `InMemoryTaskStore` with a `TaskStore` backed by a RDBMS. It uses JPA to interact with the RDBMS, providing persistence across application restarts and shared state in multi-instance deployments. - -[`push-notification-config-store-database-jpa`](./push-notification-config-store-database-jpa/README.md) - Replaces the default `InMemoryPushNotificationConfigStore` with a `PushNotificationConfigStore` backed by a RDBMS. It uses JPA to interact with the RDBMS, ensuring push notification subscriptions survive restarts. - -## Distributed Systems - -[`queue-manager-replicated`](./queue-manager-replicated/README.md) - Replaces the default `InMemoryQueueManager` with a `QueueManager` supporting replication to other A2A servers implementing the same agent. Required for multi-instance deployments. You can write your own `ReplicationStrategy`, or use the provided MicroProfile Reactive Messaging implementation with Apache Kafka, Pulsar, or AMQP. \ No newline at end of file diff --git a/extras/common/pom.xml b/extras/common/pom.xml deleted file mode 100644 index 0b829fac0..000000000 --- a/extras/common/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-extras-common - A2A Java SDK :: Extras :: Common - Common classes shared across extras modules - - - - - diff --git a/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java b/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java deleted file mode 100644 index 0c35bad7a..000000000 --- a/extras/common/src/main/java/io/a2a/extras/common/events/TaskFinalizedEvent.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.a2a.extras.common.events; - -/** - * CDI event fired when a task reaches a final state and is successfully persisted to the database. - * This event is fired AFTER the database transaction commits, making it safe for downstream - * components to assume the task is durably stored. - * - *

Used by the replicated queue manager to send the final task state before the poison pill, - * ensuring correct event ordering across instances and eliminating race conditions. - */ -public class TaskFinalizedEvent { - private final String taskId; - private final Object task; // Task type from io.a2a.spec - using Object to avoid dependency - - public TaskFinalizedEvent(String taskId, Object task) { - this.taskId = taskId; - this.task = task; - } - - public String getTaskId() { - return taskId; - } - - public Object getTask() { - return task; - } - - @Override - public String toString() { - return "TaskFinalizedEvent{taskId='" + taskId + "', task=" + task + "}"; - } -} diff --git a/extras/http-client-vertx/README.md b/extras/http-client-vertx/README.md deleted file mode 100644 index a1b48afbf..000000000 --- a/extras/http-client-vertx/README.md +++ /dev/null @@ -1,398 +0,0 @@ -# A2A Java SDK - Vert.x HTTP Client - -This module provides a Vert.x WebClient-based implementation of the `A2AHttpClient` interface for reactive, high-performance HTTP communication in the A2A Java SDK. - -## Overview - -The A2A SDK uses an `A2AHttpClient` abstraction for all HTTP communication, including fetching agent cards and making REST transport calls. By default, the SDK uses a JDK 11+ HttpClient implementation. This module provides a drop-in replacement using **Vert.x WebClient**, offering: - -- **Reactive/Async Architecture**: Built on Vert.x's event loop for non-blocking I/O -- **Better Performance**: Lower resource usage and higher throughput than blocking JDK HttpClient -- **HTTP/2 Support**: Automatic HTTP/2 negotiation via ALPN -- **Seamless Integration**: Automatic discovery via Java SPI - no code changes required - -## What It Does - -Replaces the default `JdkA2AHttpClient` with `VertxA2AHttpClient`, which uses Vert.x WebClient for all HTTP operations: - -- GET requests (synchronous and async SSE streaming) -- POST requests (synchronous and async SSE streaming) -- DELETE requests -- Agent card fetching -- REST transport communication - -The implementation maintains the same API as the JDK client but uses Vert.x's reactive architecture under the hood. - -## Problem It Solves - -### Performance & Scalability -- **JDK HttpClient**: Uses platform threads for blocking I/O operations -- **Vert.x WebClient**: Uses event loop threads with non-blocking I/O -- **Result**: Lower memory footprint, higher concurrency, better throughput - -### Reactive Integration -- Applications already using Vert.x can share the same event loop -- Avoids mixing blocking and non-blocking I/O patterns -- Better integration with reactive frameworks (Quarkus, Vert.x, etc.) - -### Resource Efficiency -- Fewer threads needed for high-concurrency scenarios -- Better connection pooling and keep-alive management -- Lower latency for streaming operations (SSE) - -## When to Use - -✅ **Recommended for:** -- Quarkus applications (Vert.x is already included) -- Reactive applications using Vert.x or reactive frameworks -- High-throughput scenarios with many concurrent requests -- Applications requiring efficient SSE streaming -- Cloud-native deployments optimizing for resource usage - -❌ **Not needed for:** -- Simple, low-volume applications -- Applications without existing Vert.x dependency -- Environments where JDK HttpClient performs adequately - -## Quick Start - -### 1. Add Dependency - -Add this module to your project's `pom.xml`: - -```xml - - io.github.a2asdk - a2a-java-sdk-http-client-vertx - ${a2a.version} - -``` - -You also need the Vert.x WebClient dependency (if not already present): - -```xml - - io.vertx - vertx-web-client - -``` - -**For Quarkus**: Vert.x is already included, so you only need to add the `a2a-java-sdk-http-client-vertx` dependency. - -### 2. Automatic Discovery (No Code Changes) - -The Vert.x HTTP client is automatically discovered via **Java SPI (Service Provider Interface)**: - -```java -// No changes needed - A2A SDK automatically uses VertxA2AHttpClient -A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999"); -AgentCard card = resolver.getAgentCard(); // Uses Vert.x under the hood - -// Client creation also uses Vert.x automatically -Client client = Client.builder(card) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) - .build(); -``` - -The `VertxA2AHttpClientProvider` has **priority 100**, which is higher than the JDK implementation's priority (50). The SDK's `A2AHttpClientFactory` uses `ServiceLoader` to discover and select the highest-priority provider available. - -### 3. No Configuration Required - -The module works out-of-the-box with sensible defaults: -- HTTP keep-alive enabled -- Automatic redirect following -- Automatic HTTP/2 negotiation - -## Usage Examples - -### Basic Usage (Automatic Discovery) - -```java -// The A2A SDK internally uses A2AHttpClient for all HTTP operations -// With vertx-http-client on the classpath, it automatically uses VertxA2AHttpClient - -// Example 1: Fetching agent card -A2ACardResolver resolver = new A2ACardResolver("http://localhost:9999"); -AgentCard card = resolver.getAgentCard(); - -// Example 2: Using REST transport (uses HTTP client internally) -Client client = Client.builder(card) - .withTransport(RESTTransport.class, new RESTTransportConfig()) - .build(); - -Message message = A2A.toUserMessage("Hello!"); -client.sendMessage(message); -``` - -### Direct Usage (Advanced) - -If you need direct access to the HTTP client (rare): - -```java -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.client.http.A2AHttpResponse; - -// Get the client via factory (returns VertxA2AHttpClient if available) -try (A2AHttpClient client = A2AHttpClientFactory.create()) { - // Simple GET request - A2AHttpResponse response = client.createGet() - .url("https://api.example.com/data") - .addHeader("Authorization", "Bearer token") - .get(); - - if (response.success()) { - System.out.println(response.body()); - } -} -``` - -### POST Request with JSON Body - -```java -try (A2AHttpClient client = A2AHttpClientFactory.create()) { - A2AHttpResponse response = client.createPost() - .url("https://api.example.com/submit") - .addHeader("Content-Type", "application/json") - .body("{\"key\":\"value\"}") - .post(); - - System.out.println("Status: " + response.status()); -} -``` - -### Server-Sent Events (SSE) Streaming - -```java -try (A2AHttpClient client = A2AHttpClientFactory.create()) { - CompletableFuture future = client.createGet() - .url("https://api.example.com/stream") - .getAsyncSSE( - message -> System.out.println("Received: " + message), - error -> error.printStackTrace(), - () -> System.out.println("Stream complete") - ); - - // Do other work while streaming... - future.join(); // Wait for completion if needed -} -``` - -## Advanced Configuration - -### Using an External Vert.x Instance - -In Quarkus or other CDI environments, you can inject an existing Vert.x instance: - -#### Quarkus Example - -```java -import io.vertx.core.Vertx; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class MyService { - - @Inject - Vertx vertx; - - public void doSomething() { - // VertxA2AHttpClient will automatically discover and use the CDI-managed Vertx - try (A2AHttpClient client = A2AHttpClientFactory.create()) { - // The client internally reuses the injected Vertx instance - A2AHttpResponse response = client.createGet() - .url("https://example.com") - .get(); - } - } -} -``` - -The `VertxA2AHttpClient` constructor automatically checks for a CDI-managed `Vertx` instance and reuses it if available. This ensures that your entire application shares the same Vert.x event loop. - -#### Manual Vertx Instance (Non-CDI) - -If you're not using CDI but want to share a Vert.x instance: - -```java -import io.a2a.client.http.VertxA2AHttpClient; -import io.vertx.core.Vertx; - -// Create Vertx instance once -Vertx vertx = Vertx.vertx(); - -try { - // Create client with shared Vertx instance - try (VertxA2AHttpClient client = new VertxA2AHttpClient(vertx)) { - A2AHttpResponse response = client.createGet() - .url("https://example.com") - .get(); - } - // Client is closed, but Vertx instance remains open -} finally { - // Close Vertx when application shuts down - vertx.close(); -} -``` - -### Custom WebClient Configuration - -For advanced use cases requiring custom Vert.x WebClient configuration, you can create your own provider: - -```java -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.VertxA2AHttpClient; -import io.vertx.core.Vertx; -import io.vertx.ext.web.client.WebClient; -import io.vertx.ext.web.client.WebClientOptions; - -// Create custom Vertx instance with specific options -Vertx vertx = Vertx.vertx(); - -// Note: VertxA2AHttpClient doesn't expose WebClient customization directly -// For custom WebClient options, you would need to extend VertxA2AHttpClient -// or configure Vert.x-level options -``` - -## How It Works - -### Service Provider Interface (SPI) - -The module uses Java's `ServiceLoader` mechanism for automatic discovery: - -1. **Provider Registration**: `META-INF/services/io.a2a.client.http.A2AHttpClientProvider` contains: - ``` - io.a2a.client.http.VertxA2AHttpClientProvider - ``` - -2. **Priority System**: Each provider has a priority: - - `VertxA2AHttpClientProvider`: **100** (when Vert.x is available) - - `JdkA2AHttpClientProvider`: **50** (always available) - -3. **Automatic Selection**: `A2AHttpClientFactory.create()` uses the highest-priority available provider - -4. **Graceful Fallback**: If Vert.x classes are not on the classpath, the provider returns priority `-1` and the SDK falls back to JDK HttpClient - -### Lifecycle Management - -#### Standalone Usage -```java -// Client owns Vertx instance -try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - // Use client -} // Both WebClient and Vertx are closed -``` - -#### CDI/Quarkus Usage -```java -// Client uses externally-managed Vertx -try (VertxA2AHttpClient client = new VertxA2AHttpClient(injectedVertx)) { - // Use client -} // Only WebClient is closed, Vertx remains open -``` - -### Thread Safety - -- **Client Instance**: Thread-safe - multiple threads can use the same client -- **Builder Instances**: NOT thread-safe - create separate builders per thread -- **Vertx Event Loop**: All I/O operations execute on Vert.x event loop threads - -## Performance Characteristics - -### Synchronous Methods (`.get()`, `.post()`, `.delete()`) - -Despite using Vert.x's async API internally, these methods block the calling thread: - -```java -A2AHttpResponse response = client.createGet() - .url("https://example.com") - .get(); // ← Blocks until response received -``` - -**Why block?** The `A2AHttpClient` interface is designed for synchronous operations to simplify SDK usage. Vert.x's async execution still provides benefits: -- Non-blocking I/O at the network layer -- Efficient connection pooling -- Lower thread usage overall - -### Async Methods (`.getAsyncSSE()`, `.postAsyncSSE()`) - -True async operation - returns immediately with a `CompletableFuture`: - -```java -CompletableFuture future = client.createGet() - .url("https://example.com/stream") - .getAsyncSSE( - message -> handleMessage(message), - error -> handleError(error), - () -> handleComplete() - ); // ← Returns immediately - -// Do other work -future.join(); // Optional: wait for completion -``` - -## Troubleshooting - -### Client Not Being Used - -**Symptom**: Logs show `JdkA2AHttpClient` instead of `VertxA2AHttpClient` - -**Cause**: Vert.x WebClient not on classpath or version incompatibility - -**Solution**: -1. Verify dependency is present: - ```bash - mvn dependency:tree | grep vertx-web-client - ``` - -2. For Quarkus, ensure Vert.x version matches: - ```xml - - io.quarkus - quarkus-vertx - - ``` - -### ClassNotFoundException for Vert.x - -**Symptom**: `ClassNotFoundException: io.vertx.core.Vertx` - -**Solution**: Add Vert.x WebClient dependency: -```xml - - io.vertx - vertx-web-client - 4.x.x - -``` - -### Memory Leaks - -**Symptom**: `Vertx` instances not being closed - -**Cause**: Not closing `VertxA2AHttpClient` when created with no-args constructor - -**Solution**: Always use try-with-resources: -```java -try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - // Use client -} // Automatically closed -``` - -## Version Compatibility - -- **Java**: 17+ (same as A2A SDK) -- **Vert.x**: 4.x (tested with 4.5.0+) -- **Quarkus**: Any version using Vert.x 4.x -- **Jakarta EE**: 9.0+ (for CDI discovery) - -## Additional Resources - -- [Vert.x WebClient Documentation](https://vertx.io/docs/vertx-web-client/java/) -- [A2A Protocol Specification](https://a2a-protocol.org/) -- [Quarkus Vert.x Guide](https://quarkus.io/guides/vertx) - ---- - -*This module is part of the A2A Java SDK extras and provides production-ready reactive HTTP support for high-performance A2A applications.* diff --git a/extras/http-client-vertx/pom.xml b/extras/http-client-vertx/pom.xml deleted file mode 100644 index 38d745f91..000000000 --- a/extras/http-client-vertx/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-http-client-vertx - - jar - - Java SDK A2A HTTP Client - Vert.x Implementation - Vert.x implementation for A2A HTTP Client - - - - ${project.groupId} - a2a-java-sdk-http-client - - - io.vertx - vertx-web-client - provided - - - - org.junit.jupiter - junit-jupiter-api - test - - - - org.mock-server - mockserver-netty - test - - - - diff --git a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClient.java b/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClient.java deleted file mode 100644 index b6afce027..000000000 --- a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClient.java +++ /dev/null @@ -1,554 +0,0 @@ -package io.a2a.client.http; - -import static java.net.HttpURLConnection.HTTP_FORBIDDEN; -import static java.net.HttpURLConnection.HTTP_MULT_CHOICE; -import static java.net.HttpURLConnection.HTTP_OK; -import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -import org.jspecify.annotations.Nullable; - -import io.a2a.common.A2AErrorMessages; -import io.vertx.core.Vertx; -import io.vertx.core.buffer.Buffer; -import io.vertx.ext.web.client.HttpRequest; -import io.vertx.ext.web.client.HttpResponse; -import io.vertx.ext.web.client.WebClient; -import io.vertx.ext.web.client.WebClientOptions; -import io.vertx.ext.web.codec.BodyCodec; -import jakarta.enterprise.context.spi.CreationalContext; -import jakarta.enterprise.inject.spi.Bean; -import jakarta.enterprise.inject.spi.BeanManager; -import jakarta.enterprise.inject.spi.CDI; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Vert.x WebClient-based implementation of {@link A2AHttpClient}. - * - *

- * This implementation uses Vert.x's reactive HTTP client to execute requests. - * For synchronous methods ({@link GetBuilder#get()}, {@link PostBuilder#post()}, {@link DeleteBuilder#delete()}), - * the implementation blocks the calling thread until the asynchronous operation completes. - * For SSE streaming methods, the implementation returns immediately with a - * {@link CompletableFuture} and streams events asynchronously via callbacks. - * - *

Lifecycle Management

- *

- * This client implements {@link AutoCloseable} and should be closed when no longer needed: - *

{@code
- * try (VertxA2AHttpClient client = new VertxA2AHttpClient()) {
- *     A2AHttpResponse response = client.createGet()
- *         .url("https://example.com/api")
- *         .get();
- *     // Use response
- * }
- * }
- * - *

- * If constructed with the no-args constructor, the client creates and owns a - * {@link Vertx} instance which will be closed when {@link #close()} is called. - * If constructed with an external {@link Vertx} instance, only the WebClient is - * closed, leaving the Vertx instance management to the caller. - * - *

Thread Safety

- *

- * This client is thread-safe. Multiple threads can create and execute requests - * concurrently. However, individual builder instances are NOT thread-safe and should - * not be shared across threads. - * - *

HTTP/2 Support

- *

- * Vert.x WebClient automatically negotiates HTTP/2 when supported by the server - * via ALPN. No explicit configuration is required. - * - *

Usage Examples

- * - *

Simple GET Request

- *
{@code
- * try (VertxA2AHttpClient client = new VertxA2AHttpClient()) {
- *     A2AHttpResponse response = client.createGet()
- *         .url("https://api.example.com/data")
- *         .addHeader("Authorization", "Bearer token")
- *         .get();
- *
- *     if (response.success()) {
- *         System.out.println(response.body());
- *     }
- * }
- * }
- * - *

POST Request with JSON Body

- *
{@code
- * try (VertxA2AHttpClient client = new VertxA2AHttpClient()) {
- *     A2AHttpResponse response = client.createPost()
- *         .url("https://api.example.com/submit")
- *         .addHeader("Content-Type", "application/json")
- *         .body("{\"key\":\"value\"}")
- *         .post();
- *
- *     System.out.println("Status: " + response.status());
- * }
- * }
- * - *

Async SSE Streaming

- *
{@code
- * try (VertxA2AHttpClient client = new VertxA2AHttpClient()) {
- *     CompletableFuture future = client.createGet()
- *         .url("https://api.example.com/stream")
- *         .getAsyncSSE(
- *             message -> System.out.println("Received: " + message),
- *             error -> error.printStackTrace(),
- *             () -> System.out.println("Stream complete")
- *         );
- *
- *     // Do other work while streaming...
- *     future.join(); // Wait for completion if needed
- * }
- * }
- */ -public class VertxA2AHttpClient implements A2AHttpClient, AutoCloseable { - - private final Vertx vertx; - private final WebClient webClient; - private boolean ownsVertx; - private static final Logger log = Logger.getLogger(VertxA2AHttpClient.class.getName()); - - /** - * Creates a new VertxA2AHttpClient with an internally managed Vert.x instance. - * - *

- * The client creates a new {@link Vertx} instance and {@link WebClient} configured - * with HTTP keep-alive and automatic redirect following. When {@link #close()} is called, - * both the WebClient and Vertx instance are closed. - * - *

- * Important: Always call {@link #close()} when done with this client - * to prevent resource leaks. - * - * @see #VertxA2AHttpClient(Vertx) for using an externally managed Vertx instance - */ - public VertxA2AHttpClient() { - this.vertx = createVertx(); - WebClientOptions options = new WebClientOptions() - .setFollowRedirects(true) - .setKeepAlive(true); - this.webClient = WebClient.create(vertx, options); - log.fine("Vert.x client is ready."); - } - - private Vertx createVertx() { - try { - BeanManager beanManager = CDI.current().getBeanManager(); - Set> beans = beanManager.getBeans(Vertx.class); - if (beans != null && !beans.isEmpty()) { - this.ownsVertx = false; - Bean bean = beans.iterator().next(); - CreationalContext context = beanManager.createCreationalContext(bean); - return (Vertx) beanManager.getReference(bean, Vertx.class, context); - } - } catch (Exception ex) { - log.log(Level.FINE, "Error loading vertx from CDI error details", ex); - } - this.ownsVertx = true; - return Vertx.vertx(); - } - - /** - * Creates a new VertxA2AHttpClient using an externally managed Vert.x instance. - * - *

- * The client creates a {@link WebClient} using the provided {@link Vertx} instance. - * When {@link #close()} is called, only the WebClient is closed; the Vertx instance - * remains open and must be managed by the caller. - * - *

- * This constructor is useful in environments where Vert.x is already managed, - * such as Quarkus applications. - * - * @param vertx the Vert.x instance to use; must not be null - * @throws NullPointerException if vertx is null - */ - public VertxA2AHttpClient(Vertx vertx) { - if (vertx == null) { - throw new NullPointerException("vertx must not be null"); - } - this.vertx = vertx; - this.ownsVertx = false; - WebClientOptions options = new WebClientOptions() - .setFollowRedirects(true) - .setKeepAlive(true); - this.webClient = WebClient.create(vertx, options); - log.fine("Vert.x client is ready."); - } - - /** - * Closes this HTTP client and releases associated resources. - * - *

- * This method always closes the WebClient. If the client was created with the - * no-args constructor (and thus owns the Vert.x instance), the Vertx instance is - * also closed. Otherwise, the Vertx instance is left open for the caller to manage. - */ - @Override - public void close() { - webClient.close(); - if (ownsVertx) { - vertx.close(); - } - } - - @Override - public GetBuilder createGet() { - return new VertxGetBuilder(); - } - - @Override - public PostBuilder createPost() { - return new VertxPostBuilder(); - } - - @Override - public DeleteBuilder createDelete() { - return new VertxDeleteBuilder(); - } - - private abstract class VertxBuilder> implements Builder { - - protected String url = ""; - protected Map headers = new HashMap<>(); - - @Override - public T url(String url) { - this.url = url; - return self(); - } - - @Override - public T addHeader(String name, String value) { - headers.put(name, value); - return self(); - } - - @Override - public T addHeaders(Map headers) { - if (headers != null && !headers.isEmpty()) { - for (Map.Entry entry : headers.entrySet()) { - addHeader(entry.getKey(), entry.getValue()); - } - } - return self(); - } - - @SuppressWarnings("unchecked") - T self() { - return (T) this; - } - } - - /** - * Common method to execute synchronous HTTP requests (GET, POST, DELETE). - * - * @param request the HTTP request configured with method and URL - * @param headers custom headers to add to the request - * @param bodyBuffer optional body buffer for POST requests (null for GET/DELETE) - * @return the HTTP response - * @throws IOException if the request fails or returns 401/403 - * @throws InterruptedException if the thread is interrupted while waiting - */ - private A2AHttpResponse executeSyncRequest( - HttpRequest request, - Map headers, - @Nullable Buffer bodyBuffer) throws IOException, InterruptedException { - - // Add headers - for (Map.Entry entry : headers.entrySet()) { - request.putHeader(entry.getKey(), entry.getValue()); - } - - CountDownLatch latch = new CountDownLatch(1); - AtomicReference responseRef = new AtomicReference<>(); - AtomicReference errorRef = new AtomicReference<>(); - - // Send with or without body - if (bodyBuffer != null) { - request.sendBuffer(bodyBuffer, ar -> handleResponse(ar, responseRef, errorRef, latch)); - } else { - request.send(ar -> handleResponse(ar, responseRef, errorRef, latch)); - } - - latch.await(); - - if (errorRef.get() != null) { - Throwable error = errorRef.get(); - if (error instanceof IOException) { - throw (IOException) error; - } - if (error instanceof InterruptedException) { - throw (InterruptedException) error; - } - throw new IOException("Request failed", error); - } - A2AHttpResponse finalResponse = responseRef.get(); - if(finalResponse == null) { - throw new IllegalStateException("No response from http request"); - } - return finalResponse; - } - - /** - * Handles the HTTP response callback, checking for auth errors and populating response/error refs. - */ - private void handleResponse( - io.vertx.core.AsyncResult> ar, - AtomicReference responseRef, - AtomicReference errorRef, - CountDownLatch latch) { - - if (ar.succeeded()) { - HttpResponse response = ar.result(); - int status = response.statusCode(); - - // Check for authentication/authorization errors - switch (status) { - case HTTP_UNAUTHORIZED -> errorRef.set(new IOException(A2AErrorMessages.AUTHENTICATION_FAILED)); - case HTTP_FORBIDDEN -> errorRef.set(new IOException(A2AErrorMessages.AUTHORIZATION_FAILED)); - default -> { - String body = response.bodyAsString(); - responseRef.set(new VertxHttpResponse(status, body != null ? body : "")); - } - } - } else { - errorRef.set(ar.cause()); - } - latch.countDown(); - } - - /** - * Common method to execute async SSE requests (GET or POST). - * - * @param baseRequest the base HTTP request (HttpRequest<Buffer>) configured with method and URL - * @param headers custom headers to add to the request - * @param bodyBuffer optional body buffer for POST requests (null for GET) - * @param messageConsumer callback for each SSE message received - * @param errorConsumer callback for errors - * @param completeRunnable callback when stream completes successfully - * @return CompletableFuture that completes when the stream ends - */ - private CompletableFuture executeAsyncSSE( - HttpRequest baseRequest, - Map headers, - @Nullable Buffer bodyBuffer, - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) { - - CompletableFuture future = new CompletableFuture<>(); - AtomicBoolean successOccurred = new AtomicBoolean(false); - AtomicBoolean streamEnded = new AtomicBoolean(false); - AtomicBoolean futureCompleted = new AtomicBoolean(false); - - HttpRequest request = baseRequest - .putHeader(ACCEPT, EVENT_STREAM) - .as(BodyCodec.sseStream(stream -> { - stream.handler(event -> { - String data = event.data(); - if (data != null) { - data = data.trim(); - if (!data.isEmpty()) { - messageConsumer.accept(data); - } - } - }); - - stream.endHandler(v -> { - streamEnded.set(true); - // Only complete if we've validated success and haven't completed yet - if (successOccurred.get() && futureCompleted.compareAndSet(false, true)) { - completeRunnable.run(); - future.complete(null); - } - }); - - stream.exceptionHandler(error -> { - if (futureCompleted.compareAndSet(false, true)) { - errorConsumer.accept(error); - future.complete(null); - } - }); - })); - - // Add custom headers - for (Map.Entry entry : headers.entrySet()) { - request.putHeader(entry.getKey(), entry.getValue()); - } - - // Send with or without body - var sendFuture = (bodyBuffer != null) ? request.sendBuffer(bodyBuffer) : request.send(); - - sendFuture - .onSuccess(response -> { - // Validate status code manually since .expecting() doesn't work with SSE streams - int statusCode = response.statusCode(); - if (statusCode < 200 || statusCode >= 300) { - // Error - don't set successOccurred, just report error - if (futureCompleted.compareAndSet(false, true)) { - // Use same error messages as sync requests for consistency - IOException error = switch (statusCode) { - case HTTP_UNAUTHORIZED -> new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); - case HTTP_FORBIDDEN -> new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); - default -> new IOException("HTTP " + statusCode + ": " + response.bodyAsString()); - }; - errorConsumer.accept(error); - future.complete(null); - } - } else { - // Success - mark as successful - successOccurred.set(true); - // If stream already ended, complete now - if (streamEnded.get() && futureCompleted.compareAndSet(false, true)) { - completeRunnable.run(); - future.complete(null); - } - } - }) - .onFailure(cause -> { - if (futureCompleted.compareAndSet(false, true)) { - errorConsumer.accept(cause); - future.complete(null); - } - }); - - return future; - } - - private class VertxGetBuilder extends VertxBuilder implements A2AHttpClient.GetBuilder { - - /** - * {@inheritDoc} - * - *

- * Implementation Note: This method blocks the calling thread until - * the asynchronous HTTP request completes. The underlying Vert.x operation executes - * asynchronously on the Vert.x event loop. - * - * @throws IOException if the request fails, including: - *

    - *
  • Network errors (connection refused, timeout, etc.)
  • - *
  • HTTP 401 Unauthorized - with message from {@link A2AErrorMessages#AUTHENTICATION_FAILED}
  • - *
  • HTTP 403 Forbidden - with message from {@link A2AErrorMessages#AUTHORIZATION_FAILED}
  • - *
- * @throws InterruptedException if the thread is interrupted while waiting - */ - @Override - public A2AHttpResponse get() throws IOException, InterruptedException { - return executeSyncRequest(webClient.getAbs(url), headers, null); - } - - @Override - public CompletableFuture getAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException { - - HttpRequest request = webClient.getAbs(url); - return executeAsyncSSE(request, headers, null, messageConsumer, errorConsumer, completeRunnable); - } - } - - private class VertxPostBuilder extends VertxBuilder implements A2AHttpClient.PostBuilder { - - private String body = ""; - - @Override - public PostBuilder body(String body) { - this.body = body; - return self(); - } - - /** - * {@inheritDoc} - * - *

- * Implementation Note: This method blocks the calling thread until - * the asynchronous HTTP request completes. The underlying Vert.x operation executes - * asynchronously on the Vert.x event loop. - * - * @throws IOException if the request fails, including: - *

    - *
  • Network errors (connection refused, timeout, etc.)
  • - *
  • HTTP 401 Unauthorized - with message from {@link A2AErrorMessages#AUTHENTICATION_FAILED}
  • - *
  • HTTP 403 Forbidden - with message from {@link A2AErrorMessages#AUTHORIZATION_FAILED}
  • - *
- * @throws InterruptedException if the thread is interrupted while waiting - */ - @Override - public A2AHttpResponse post() throws IOException, InterruptedException { - Buffer bodyBuffer = Buffer.buffer(body, StandardCharsets.UTF_8.name()); - return executeSyncRequest(webClient.postAbs(url), headers, bodyBuffer); - } - - @Override - public CompletableFuture postAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException { - - HttpRequest request = webClient.postAbs(url); - Buffer bodyBuffer = Buffer.buffer(body, StandardCharsets.UTF_8.name()); - return executeAsyncSSE(request, headers, bodyBuffer, messageConsumer, errorConsumer, completeRunnable); - } - } - - private class VertxDeleteBuilder extends VertxBuilder implements A2AHttpClient.DeleteBuilder { - - /** - * {@inheritDoc} - * - *

- * Implementation Note: This method blocks the calling thread until - * the asynchronous HTTP request completes. The underlying Vert.x operation executes - * asynchronously on the Vert.x event loop. - * - * @throws IOException if the request fails, including: - *

    - *
  • Network errors (connection refused, timeout, etc.)
  • - *
  • HTTP 401 Unauthorized - with message from {@link A2AErrorMessages#AUTHENTICATION_FAILED}
  • - *
  • HTTP 403 Forbidden - with message from {@link A2AErrorMessages#AUTHORIZATION_FAILED}
  • - *
- * @throws InterruptedException if the thread is interrupted while waiting - */ - @Override - public A2AHttpResponse delete() throws IOException, InterruptedException { - return executeSyncRequest(webClient.deleteAbs(url), headers, null); - } - } - - private record VertxHttpResponse(int status, String body) implements A2AHttpResponse { - - @Override - public int status() { - return status; - } - - @Override - public boolean success() { - return status >= HTTP_OK && status < HTTP_MULT_CHOICE; - } - - @Override - public String body() { - return body; - } - } -} diff --git a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClientProvider.java b/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClientProvider.java deleted file mode 100644 index e802e1df1..000000000 --- a/extras/http-client-vertx/src/main/java/io/a2a/client/http/VertxA2AHttpClientProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.a2a.client.http; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Service provider for {@link VertxA2AHttpClient}. - * - *

- * This provider has a higher priority (100) than the JDK implementation and will be - * preferred when the Vert.x dependencies are available on the classpath. - * - *

- * If Vert.x classes are not available at runtime, this provider will check for their - * presence and throw an {@link IllegalStateException} when attempting to create a client. - * The ServiceLoader mechanism will skip this provider and fall back to the JDK implementation. - */ -public final class VertxA2AHttpClientProvider implements A2AHttpClientProvider { - - private static final boolean VERTX_AVAILABLE = isVertxAvailable(); - private static final Logger log = Logger.getLogger(VertxA2AHttpClientProvider.class.getName()); - - private static boolean isVertxAvailable() { - try { - Class.forName("io.vertx.core.Vertx"); - Class.forName("io.vertx.ext.web.client.WebClient"); - return true; - } catch (ClassNotFoundException ex) { - Logger.getLogger(VertxA2AHttpClientProvider.class.getName()).log(Level.FINE, "Vert.x classes are not available on the classpath. Falling back to other providers.", ex); - return false; - } - } - - @Override - public A2AHttpClient create() { - if (!VERTX_AVAILABLE) { - throw new IllegalStateException( - "Vert.x classes are not available on the classpath. " - + "Add io.vertx:vertx-web-client dependency or use the JDK HTTP client implementation."); - } - - try { - Class clientClass = Class.forName("io.a2a.client.http.VertxA2AHttpClient"); - return (A2AHttpClient) clientClass.getDeclaredConstructor().newInstance(); - } catch (Exception e) { - throw new IllegalStateException("Failed to create VertxA2AHttpClient instance", e); - } - } - - @Override - public int priority() { - return VERTX_AVAILABLE ? 100 : -1; // Higher priority when available, negative when not - } - - @Override - public String name() { - return "vertx"; - } -} diff --git a/extras/http-client-vertx/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider b/extras/http-client-vertx/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider deleted file mode 100644 index 9d6a67c3b..000000000 --- a/extras/http-client-vertx/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.http.VertxA2AHttpClientProvider diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientFactoryTest.java b/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientFactoryTest.java deleted file mode 100644 index 2ac3eac94..000000000 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientFactoryTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.a2a.client.http; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.Test; - -public class VertxA2AHttpClientFactoryTest { - - @Test - public void testCreateReturnsVertxClient() { - // When both JDK and Vertx are on classpath, Vertx should be preferred due to higher priority - A2AHttpClient client = A2AHttpClientFactory.create(); - assertNotNull(client); - assertInstanceOf(VertxA2AHttpClient.class, client, - "Factory should return VertxA2AHttpClient when Vertx is available"); - // Clean up - if (client instanceof AutoCloseable) { - try { - ((AutoCloseable) client).close(); - } catch (Exception e) { - fail("Failed to close client: " + e.getMessage()); - } - } - } - - @Test - public void testCreateWithVertxProviderName() { - A2AHttpClient client = A2AHttpClientFactory.create("vertx"); - assertNotNull(client); - assertInstanceOf(VertxA2AHttpClient.class, client, - "Factory should return VertxA2AHttpClient when 'vertx' provider is requested"); - // Clean up - if (client instanceof AutoCloseable) { - try { - ((AutoCloseable) client).close(); - } catch (Exception e) { - fail("Failed to close client: " + e.getMessage()); - } - } - } - - @Test - public void testVertxClientIsUsable() { - A2AHttpClient client = A2AHttpClientFactory.create("vertx"); - assertNotNull(client); - - // Verify we can create builders - A2AHttpClient.GetBuilder getBuilder = client.createGet(); - assertNotNull(getBuilder, "Should be able to create GET builder"); - - A2AHttpClient.PostBuilder postBuilder = client.createPost(); - assertNotNull(postBuilder, "Should be able to create POST builder"); - - A2AHttpClient.DeleteBuilder deleteBuilder = client.createDelete(); - assertNotNull(deleteBuilder, "Should be able to create DELETE builder"); - - // Clean up - if (client instanceof AutoCloseable) { - try { - ((AutoCloseable) client).close(); - } catch (Exception e) { - fail("Failed to close client: " + e.getMessage()); - } - } - } -} diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientIntegrationTest.java b/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientIntegrationTest.java deleted file mode 100644 index f945aecde..000000000 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientIntegrationTest.java +++ /dev/null @@ -1,212 +0,0 @@ -package io.a2a.client.http; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import io.a2a.common.A2AErrorMessages; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; - -public class VertxA2AHttpClientIntegrationTest { - - private ClientAndServer mockServer; - private VertxA2AHttpClient client; - - @BeforeEach - public void setup() { - mockServer = ClientAndServer.startClientAndServer(0); // Use random port - client = new VertxA2AHttpClient(); - } - - @AfterEach - public void teardown() { - if (client != null) { - client.close(); - } - if (mockServer != null) { - mockServer.stop(); - } - } - - private String getBaseUrl() { - return "http://localhost:" + mockServer.getPort(); - } - - @Test - public void testGetRequestSuccess() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/test")) - .respond(response().withStatusCode(200).withBody("success")); - - A2AHttpResponse response = client.createGet() - .url(getBaseUrl() + "/test") - .get(); - - assertEquals(200, response.status()); - assertTrue(response.success()); - assertEquals("success", response.body()); - } - - @Test - public void testPostRequestSuccess() throws Exception { - mockServer - .when(request() - .withMethod("POST") - .withPath("/test") - .withBody("{\"key\":\"value\"}")) - .respond(response().withStatusCode(201).withBody("created")); - - A2AHttpResponse response = client.createPost() - .url(getBaseUrl() + "/test") - .body("{\"key\":\"value\"}") - .post(); - - assertEquals(201, response.status()); - assertTrue(response.success()); - assertEquals("created", response.body()); - } - - @Test - public void testDeleteRequestSuccess() throws Exception { - mockServer - .when(request().withMethod("DELETE").withPath("/test")) - .respond(response().withStatusCode(204)); - - A2AHttpResponse response = client.createDelete() - .url(getBaseUrl() + "/test") - .delete(); - - assertEquals(204, response.status()); - assertTrue(response.success()); - } - - @Test - public void test401AuthenticationErrorOnGet() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/test")) - .respond(response().withStatusCode(401)); - - Exception exception = assertThrows(java.io.IOException.class, () -> { - client.createGet() - .url(getBaseUrl() + "/test") - .get(); - }); - - assertEquals(A2AErrorMessages.AUTHENTICATION_FAILED, exception.getMessage()); - } - - @Test - public void test403AuthorizationErrorOnGet() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/test")) - .respond(response().withStatusCode(403)); - - Exception exception = assertThrows(java.io.IOException.class, () -> { - client.createGet() - .url(getBaseUrl() + "/test") - .get(); - }); - - assertEquals(A2AErrorMessages.AUTHORIZATION_FAILED, exception.getMessage()); - } - - @Test - public void test401AuthenticationErrorOnPost() throws Exception { - mockServer - .when(request().withMethod("POST").withPath("/test")) - .respond(response().withStatusCode(401)); - - Exception exception = assertThrows(java.io.IOException.class, () -> { - client.createPost() - .url(getBaseUrl() + "/test") - .body("{}") - .post(); - }); - - assertEquals(A2AErrorMessages.AUTHENTICATION_FAILED, exception.getMessage()); - } - - @Test - public void test403AuthorizationErrorOnPost() throws Exception { - mockServer - .when(request().withMethod("POST").withPath("/test")) - .respond(response().withStatusCode(403)); - - Exception exception = assertThrows(java.io.IOException.class, () -> { - client.createPost() - .url(getBaseUrl() + "/test") - .body("{}") - .post(); - }); - - assertEquals(A2AErrorMessages.AUTHORIZATION_FAILED, exception.getMessage()); - } - - @Test - public void test401AuthenticationErrorOnDelete() throws Exception { - mockServer - .when(request().withMethod("DELETE").withPath("/test")) - .respond(response().withStatusCode(401)); - - Exception exception = assertThrows(java.io.IOException.class, () -> { - client.createDelete() - .url(getBaseUrl() + "/test") - .delete(); - }); - - assertEquals(A2AErrorMessages.AUTHENTICATION_FAILED, exception.getMessage()); - } - - @Test - public void testHeaderPropagation() throws Exception { - mockServer - .when(request() - .withMethod("GET") - .withPath("/test") - .withHeader("Authorization", "Bearer token") - .withHeader("X-Custom-Header", "custom-value")) - .respond(response().withStatusCode(200).withBody("ok")); - - A2AHttpResponse response = client.createGet() - .url(getBaseUrl() + "/test") - .addHeader("Authorization", "Bearer token") - .addHeader("X-Custom-Header", "custom-value") - .get(); - - assertEquals(200, response.status()); - assertEquals("ok", response.body()); - } - - @Test - public void testNonSuccessStatusCode() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/test")) - .respond(response().withStatusCode(500).withBody("Internal Server Error")); - - A2AHttpResponse response = client.createGet() - .url(getBaseUrl() + "/test") - .get(); - - assertEquals(500, response.status()); - assertFalse(response.success()); - assertEquals("Internal Server Error", response.body()); - } - - @Test - public void test404NotFound() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/test")) - .respond(response().withStatusCode(404).withBody("Not Found")); - - A2AHttpResponse response = client.createGet() - .url(getBaseUrl() + "/test") - .get(); - - assertEquals(404, response.status()); - assertFalse(response.success()); - assertEquals("Not Found", response.body()); - } -} diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientSSETest.java b/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientSSETest.java deleted file mode 100644 index 64b1dec54..000000000 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientSSETest.java +++ /dev/null @@ -1,253 +0,0 @@ -package io.a2a.client.http; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -import io.a2a.common.A2AErrorMessages; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -public class VertxA2AHttpClientSSETest { - - private ClientAndServer mockServer; - private VertxA2AHttpClient client; - - @BeforeEach - public void setup() { - mockServer = ClientAndServer.startClientAndServer(0); // Use random port - client = new VertxA2AHttpClient(); - } - - @AfterEach - public void teardown() { - if (client != null) { - client.close(); - } - if (mockServer != null) { - mockServer.stop(); - } - } - - private String getBaseUrl() { - return "http://localhost:" + mockServer.getPort(); - } - - @Test - public void testGetAsyncSSE() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: event1\n\ndata: event2\n\ndata: event3\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS), "Expected completion handler to be called"); - assertNull(error.get(), "Expected no errors"); - assertFalse(events.isEmpty(), "Expected to receive events"); - assertTrue(events.contains("event1"), "Expected event1"); - assertTrue(events.contains("event2"), "Expected event2"); - assertTrue(events.contains("event3"), "Expected event3"); - } - - @Test - public void testPostAsyncSSE() throws Exception { - mockServer - .when(request() - .withMethod("POST") - .withPath("/sse") - .withBody("{\"subscribe\":true}")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: message1\n\ndata: message2\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createPost() - .url(getBaseUrl() + "/sse") - .body("{\"subscribe\":true}") - .postAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS), "Expected completion handler to be called"); - assertNull(error.get(), "Expected no errors"); - assertFalse(events.isEmpty(), "Expected to receive events"); - assertTrue(events.contains("message1"), "Expected message1"); - assertTrue(events.contains("message2"), "Expected message2"); - } - - @Test - public void testSSEDataPrefixStripping() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: content here\n\ndata:no space\n\ndata: extra spaces \n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - assertNull(error.get()); - assertTrue(events.contains("content here"), "Should have stripped 'data: ' prefix"); - assertTrue(events.contains("no space"), "Should handle 'data:' without space"); - assertTrue(events.contains("extra spaces"), "Should trim whitespace"); - } - - @Test - public void testSSEAuthenticationError() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response().withStatusCode(401)); - - CountDownLatch errorLatch = new CountDownLatch(1); - AtomicReference error = new AtomicReference<>(); - AtomicBoolean completed = new AtomicBoolean(false); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - msg -> {}, - e -> { - error.set(e); - errorLatch.countDown(); - }, - () -> completed.set(true) - ); - - assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); - assertNotNull(error.get(), "Expected an error"); - assertTrue(error.get() instanceof IOException, "Expected IOException"); - assertTrue(error.get().getMessage().contains("Authentication failed"), - "Expected authentication error message but got: " + error.get().getMessage()); - assertFalse(completed.get(), "Should not call completion handler on error"); - } - - @Test - public void testSSEAuthorizationError() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response().withStatusCode(403)); - - CountDownLatch errorLatch = new CountDownLatch(1); - AtomicReference error = new AtomicReference<>(); - AtomicBoolean completed = new AtomicBoolean(false); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - msg -> {}, - e -> { - error.set(e); - errorLatch.countDown(); - }, - () -> completed.set(true) - ); - - assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Expected error handler to be called"); - assertNotNull(error.get(), "Expected an error"); - assertTrue(error.get() instanceof IOException, "Expected IOException"); - assertTrue(error.get().getMessage().contains("Authorization failed"), - "Expected authorization error message but got: " + error.get().getMessage()); - assertFalse(completed.get(), "Should not call completion handler on error"); - } - - @Test - public void testSSEEmptyLinesIgnored() throws Exception { - mockServer - .when(request().withMethod("GET").withPath("/sse")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: first\n\n\n\ndata: second\n\ndata: \n\ndata: third\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - assertNull(error.get()); - assertEquals(3, events.size(), "Should have received 3 non-empty events"); - assertTrue(events.contains("first")); - assertTrue(events.contains("second")); - assertTrue(events.contains("third")); - } - - @Test - public void testSSEHeaderPropagation() throws Exception { - mockServer - .when(request() - .withMethod("GET") - .withPath("/sse") - .withHeader("Accept", "text/event-stream") - .withHeader("Authorization", "Bearer token")) - .respond(response() - .withStatusCode(200) - .withHeader("Content-Type", "text/event-stream") - .withBody("data: authenticated\n\n")); - - CountDownLatch latch = new CountDownLatch(1); - List events = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - CompletableFuture future = client.createGet() - .url(getBaseUrl() + "/sse") - .addHeader("Authorization", "Bearer token") - .getAsyncSSE( - events::add, - error::set, - latch::countDown - ); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - assertNull(error.get()); - assertTrue(events.contains("authenticated")); - } -} diff --git a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientTest.java b/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientTest.java deleted file mode 100644 index 55e9afd94..000000000 --- a/extras/http-client-vertx/src/test/java/io/a2a/client/http/VertxA2AHttpClientTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package io.a2a.client.http; - -import static org.junit.jupiter.api.Assertions.*; - -import io.vertx.core.Vertx; -import org.junit.jupiter.api.Test; - -public class VertxA2AHttpClientTest { - - @Test - public void testNoArgsConstructor() { - VertxA2AHttpClient client = new VertxA2AHttpClient(); - assertNotNull(client); - client.close(); - } - - @Test - public void testVertxParameterConstructor() { - Vertx vertx = Vertx.vertx(); - VertxA2AHttpClient client = new VertxA2AHttpClient(vertx); - assertNotNull(client); - client.close(); - vertx.close(); - } - - @Test - public void testVertxParameterConstructorNullThrows() { - assertThrows(NullPointerException.class, () -> { - new VertxA2AHttpClient(null); - }); - } - - @Test - public void testCreateGet() { - try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - A2AHttpClient.GetBuilder builder = client.createGet(); - assertNotNull(builder); - } - } - - @Test - public void testCreatePost() { - try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - A2AHttpClient.PostBuilder builder = client.createPost(); - assertNotNull(builder); - } - } - - @Test - public void testCreateDelete() { - try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - A2AHttpClient.DeleteBuilder builder = client.createDelete(); - assertNotNull(builder); - } - } - - @Test - public void testBuilderUrlSetting() { - try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - A2AHttpClient.GetBuilder builder = client.createGet(); - A2AHttpClient.GetBuilder result = builder.url("https://example.com"); - assertSame(builder, result, "Builder should return itself for method chaining"); - } - } - - @Test - public void testBuilderHeaderSetting() { - try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - A2AHttpClient.GetBuilder builder = client.createGet(); - A2AHttpClient.GetBuilder result = builder.addHeader("Accept", "application/json"); - assertSame(builder, result, "Builder should return itself for method chaining"); - } - } - - @Test - public void testBuilderMethodChaining() { - try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - A2AHttpClient.GetBuilder builder = client.createGet() - .url("https://example.com") - .addHeader("Accept", "application/json") - .addHeader("Authorization", "Bearer token"); - assertNotNull(builder); - } - } - - @Test - public void testPostBuilderBody() { - try (VertxA2AHttpClient client = new VertxA2AHttpClient()) { - A2AHttpClient.PostBuilder builder = client.createPost(); - A2AHttpClient.PostBuilder result = builder.body("{\"key\":\"value\"}"); - assertSame(builder, result, "Builder should return itself for method chaining"); - } - } -} diff --git a/extras/opentelemetry/client-propagation/pom.xml b/extras/opentelemetry/client-propagation/pom.xml deleted file mode 100644 index f4a802155..000000000 --- a/extras/opentelemetry/client-propagation/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-java-sdk-opentelemetry-client-propagation - - A2A Java SDK :: Extras :: Opentelemetry :: Client Propagation - OpenTelemetry client propagation support for A2A Java SDK - - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - - - org.slf4j - slf4j-api - - - org.junit.jupiter - junit-jupiter - test - - - org.mockito - mockito-core - test - - - org.mockito - mockito-junit-jupiter - test - - - - diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java deleted file mode 100644 index 53cd134bd..000000000 --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransport.java +++ /dev/null @@ -1,123 +0,0 @@ -package io.a2a.extras.opentelemetry.client.propagation; - -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.context.Context; -import io.opentelemetry.context.propagation.TextMapSetter; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import org.jspecify.annotations.Nullable; - -public class OpenTelemetryClientPropagatorTransport implements ClientTransport { - - private final OpenTelemetry openTelemetry; - private final ClientTransport delegate; - - private static final TextMapSetter> MAP_SETTER = new TextMapSetter>() { - @Override - public void set(@Nullable Map carrier, String key, String value) { - if (carrier != null) { - carrier.put(key, value); - } - } - }; - - public OpenTelemetryClientPropagatorTransport(ClientTransport delegate, OpenTelemetry openTelemetry) { - this.delegate = delegate; - this.openTelemetry = openTelemetry; - } - - private ClientCallContext propagateContext(@Nullable ClientCallContext context) { - ClientCallContext clientContext; - if (context == null) { - clientContext = new ClientCallContext(Map.of(), new HashMap<>()); - } else { - clientContext = new ClientCallContext(context.getState(), new HashMap<>(context.getHeaders())); - } - openTelemetry.getPropagators().getTextMapPropagator().inject(Context.current(), clientContext.getHeaders(), MAP_SETTER); - return clientContext; - } - - @Override - public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException { - return delegate.sendMessage(request, propagateContext(context)); - } - - @Override - public void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - delegate.sendMessageStreaming(request, eventConsumer, errorConsumer, propagateContext(context)); - } - - @Override - public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException { - return delegate.getTask(request, propagateContext(context)); - } - - @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { - return delegate.cancelTask(request, propagateContext(context)); - } - - @Override - public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { - return delegate.listTasks(request, propagateContext(context)); - } - - @Override - public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException { - return delegate.createTaskPushNotificationConfiguration(request, propagateContext(context)); - } - - @Override - public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - return delegate.getTaskPushNotificationConfiguration(request, propagateContext(context)); - } - - @Override - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - return delegate.listTaskPushNotificationConfigurations(request, propagateContext(context)); - } - - @Override - public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - delegate.deleteTaskPushNotificationConfigurations(request, propagateContext(context)); - } - - @Override - public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - delegate.subscribeToTask(request, eventConsumer, errorConsumer, propagateContext(context)); - } - - @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - return delegate.getExtendedAgentCard(propagateContext(context)); - } - - @Override - public void close() { - delegate.close(); - } -} diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java deleted file mode 100644 index a8c83968c..000000000 --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/OpenTelemetryClientPropagatorTransportWrapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.a2a.extras.opentelemetry.client.propagation; - -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.client.transport.spi.ClientTransportWrapper; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.trace.Tracer; - -/** - * OpenTelemetry client transport wrapper that adds opentelemetry propagation to A2A client calls. - * - *

This wrapper is automatically discovered via Java's ServiceLoader mechanism. - * To enable tracing, add a {@link Tracer} instance to the transport configuration: - *

{@code
- * ClientTransportConfig config = new JSONRPCTransportConfig();
- * config.setParameters(Map.of(
- *     OpenTelemetryClientTransportFactory.OTEL_TRACER_KEY,
- *     openTelemetry.getTracer("my-service"),
- *     OpenTelemetryClientTransportFactory.OTEL_OPEN_TELEMETRY_KEY,
- *     openTelemetry
- * ));
- * }
- */ -public class OpenTelemetryClientPropagatorTransportWrapper implements ClientTransportWrapper { - - /** - * Configuration key for the OpenTelemetry Tracer instance. - * Value must be of type {@link Tracer}. - */ - public static final String OTEL_TRACER_KEY = "io.a2a.extras.opentelemetry.Tracer"; - public static final String OTEL_OPEN_TELEMETRY_KEY = "io.a2a.extras.opentelemetry.OpenTelemetry"; - - @Override - public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) { - Object openTelemetryObj = config.getParameters().get(OTEL_OPEN_TELEMETRY_KEY); - if (openTelemetryObj != null && openTelemetryObj instanceof OpenTelemetry openTelemetry) { - return new OpenTelemetryClientPropagatorTransport(transport, openTelemetry); - } - // No tracer configured, return unwrapped transport - return transport; - } - - @Override - public int priority() { - // Observability/tracing should be in the middle priority range - // so it can observe other wrappers but doesn't interfere with security - return 500; - } -} diff --git a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java b/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java deleted file mode 100644 index 0ca927df9..000000000 --- a/extras/opentelemetry/client-propagation/src/main/java/io/a2a/extras/opentelemetry/client/propagation/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.extras.opentelemetry.client.propagation; - -import org.jspecify.annotations.NullMarked; - diff --git a/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper deleted file mode 100644 index f1cccce71..000000000 --- a/extras/opentelemetry/client-propagation/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper +++ /dev/null @@ -1 +0,0 @@ -io.a2a.extras.opentelemetry.client.propagation.OpenTelemetryClientPropagatorTransportWrapper diff --git a/extras/opentelemetry/client/pom.xml b/extras/opentelemetry/client/pom.xml deleted file mode 100644 index e4039385f..000000000 --- a/extras/opentelemetry/client/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-java-sdk-opentelemetry-client - - A2A Java SDK :: Extras :: Opentelemetry :: Client - OpenTelemetry client support for A2A Java SDK - - - - ${project.groupId} - a2a-java-sdk-opentelemetry-common - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - - - org.slf4j - slf4j-api - - - org.junit.jupiter - junit-jupiter - test - - - org.mockito - mockito-core - test - - - org.mockito - mockito-junit-jupiter - test - - - - diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java deleted file mode 100644 index af36f3ffd..000000000 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransport.java +++ /dev/null @@ -1,491 +0,0 @@ -package io.a2a.extras.opentelemetry.client; - -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; - -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.A2AMethods; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Scope; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import org.jspecify.annotations.Nullable; - -public class OpenTelemetryClientTransport implements ClientTransport { - - private final Tracer tracer; - private final ClientTransport delegate; - - public OpenTelemetryClientTransport(ClientTransport delegate, Tracer tracer) { - this.delegate = delegate; - this.tracer = tracer; - } - - private boolean extractRequest() { - return Boolean.getBoolean(EXTRACT_REQUEST_SYS_PROPERTY); - } - - private boolean extractResponse() { - return Boolean.getBoolean(EXTRACT_RESPONSE_SYS_PROPERTY); - } - - @Override - public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SEND_MESSAGE_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_MESSAGE_METHOD); - if (request.message() != null) { - if (request.message().taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.message().taskId()); - } - if (request.message().contextId() != null) { - spanBuilder.setAttribute(GENAI_CONTEXT_ID, request.message().contextId()); - } - if (request.message().messageId() != null) { - spanBuilder.setAttribute(GENAI_MESSAGE_ID, request.message().messageId()); - } - if (request.message().role() != null) { - spanBuilder.setAttribute(GENAI_ROLE, request.message().role().name()); - } - if (request.message().extensions() != null && !request.message().extensions().isEmpty()) { - spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", request.message().extensions())); - } - spanBuilder.setAttribute(GENAI_PARTS_NUMBER, request.message().parts().size()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - EventKind result = delegate.sendMessage(request, clientContext); - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public void sendMessageStreaming(MessageSendParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_STREAMING_MESSAGE_METHOD); - if (request.message() != null) { - if (request.message().taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.message().taskId()); - } - if (request.message().contextId() != null) { - spanBuilder.setAttribute(GENAI_CONTEXT_ID, request.message().contextId()); - } - if (request.message().messageId() != null) { - spanBuilder.setAttribute(GENAI_MESSAGE_ID, request.message().messageId()); - } - if (request.message().role() != null) { - spanBuilder.setAttribute(GENAI_ROLE, request.message().role().name()); - } - if (request.message().extensions() != null && !request.message().extensions().isEmpty()) { - spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", request.message().extensions())); - } - spanBuilder.setAttribute(GENAI_PARTS_NUMBER, request.message().parts().size()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - delegate.sendMessageStreaming( - request, - new OpenTelemetryEventConsumer(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-event", eventConsumer, tracer, span.getSpanContext()), - new OpenTelemetryErrorConsumer(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-error", errorConsumer, tracer, span.getSpanContext()), - clientContext - ); - span.setStatus(StatusCode.OK); - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_METHOD); - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - Task result = delegate.getTask(request, clientContext); - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.CANCEL_TASK_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.CANCEL_TASK_METHOD); - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - Task result = delegate.cancelTask(request, clientContext); - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_METHOD); - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - if (request.contextId() != null) { - spanBuilder.setAttribute(GENAI_CONTEXT_ID, request.contextId()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - ListTasksResult result = delegate.listTasks(request, clientContext); - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public TaskPushNotificationConfig createTaskPushNotificationConfiguration(TaskPushNotificationConfig request, - @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - if (request.taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); - } - if (request.config() != null && request.config().id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, request.config().id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - TaskPushNotificationConfig result = delegate.createTaskPushNotificationConfiguration(request, clientContext); - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - if (request.taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); - } - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, request.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - TaskPushNotificationConfig result = delegate.getTaskPushNotificationConfiguration(request, clientContext); - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public ListTaskPushNotificationConfigResult listTaskPushNotificationConfigurations(ListTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - ListTaskPushNotificationConfigResult result = delegate.listTaskPushNotificationConfigurations(request, clientContext); - if (result != null && extractResponse()) { - String responseValue = result.configs().stream() - .map(TaskPushNotificationConfig::toString) - .collect(Collectors.joining(",")); - span.setAttribute(GENAI_RESPONSE, responseValue); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, - @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - if (request.taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.taskId()); - } - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, request.id()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - delegate.deleteTaskPushNotificationConfigurations(request, clientContext); - span.setStatus(StatusCode.OK); - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public void subscribeToTask(TaskIdParams request, Consumer eventConsumer, - Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.SUBSCRIBE_TO_TASK_METHOD); - if (request.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, request.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, request.toString()); - } - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - delegate.subscribeToTask( - request, - new OpenTelemetryEventConsumer(A2AMethods.SUBSCRIBE_TO_TASK_METHOD + "-event", eventConsumer, tracer, span.getSpanContext()), - new OpenTelemetryErrorConsumer(A2AMethods.SUBSCRIBE_TO_TASK_METHOD + "-error", errorConsumer, tracer, span.getSpanContext()), - clientContext - ); - span.setStatus(StatusCode.OK); - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - @Override - public AgentCard getExtendedAgentCard(@Nullable ClientCallContext context) throws A2AClientException { - ClientCallContext clientContext = createContext(context); - SpanBuilder spanBuilder = tracer.spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD).setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); - Span span = spanBuilder.startSpan(); - try (Scope scope = span.makeCurrent()) { - AgentCard result = delegate.getExtendedAgentCard(clientContext); - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - if (result != null) { - span.setStatus(StatusCode.OK); - } - return result; - } catch (Exception ex) { - span.setStatus(StatusCode.ERROR, ex.getMessage()); - throw ex; - } finally { - span.end(); - } - } - - private ClientCallContext createContext(@Nullable ClientCallContext context) { - if (context == null) { - return new ClientCallContext(Map.of(), new HashMap<>()); - } - return new ClientCallContext(context.getState(), new HashMap<>(context.getHeaders())); - } - - @Override - public void close() { - delegate.close(); - } - - private static class OpenTelemetryEventConsumer implements Consumer { - - private final Consumer delegate; - private final Tracer tracer; - private final SpanContext context; - private final String name; - - public OpenTelemetryEventConsumer(String name, Consumer delegate, Tracer tracer, SpanContext context) { - this.delegate = delegate; - this.tracer = tracer; - this.context = context; - this.name = name; - } - - @Override - public void accept(StreamingEventKind t) { - SpanBuilder spanBuilder = tracer.spanBuilder(name) - .setSpanKind(SpanKind.CLIENT); - spanBuilder.setAttribute("gen_ai.agent.a2a.streaming-event", t.toString()); - spanBuilder.addLink(context); - Span span = spanBuilder.startSpan(); - try { - delegate.accept(t); - span.setStatus(StatusCode.OK); - } finally { - span.end(); - } - } - } - - private static class OpenTelemetryErrorConsumer implements Consumer { - - private final Consumer delegate; - private final Tracer tracer; - private final SpanContext context; - private final String name; - - public OpenTelemetryErrorConsumer(String name, Consumer delegate, Tracer tracer, SpanContext context) { - this.delegate = delegate; - this.tracer = tracer; - this.context = context; - this.name = name; - } - - @Override - public void accept(Throwable t) { - if (t == null) { - return; - } - SpanBuilder spanBuilder = tracer.spanBuilder(name) - .setSpanKind(SpanKind.CLIENT); - spanBuilder.addLink(context); - Span span = spanBuilder.startSpan(); - try { - span.setStatus(StatusCode.ERROR, t.getMessage()); - delegate.accept(t); - } finally { - span.end(); - } - } - } -} diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java deleted file mode 100644 index 2f61bf280..000000000 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportWrapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.a2a.extras.opentelemetry.client; - -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.ClientTransportConfig; -import io.a2a.client.transport.spi.ClientTransportWrapper; -import io.opentelemetry.api.trace.Tracer; - -/** - * OpenTelemetry client transport wrapper that adds distributed tracing to A2A client calls. - * - *

This wrapper is automatically discovered via Java's ServiceLoader mechanism. - * To enable tracing, add a {@link Tracer} instance to the transport configuration: - *

{@code
- * ClientTransportConfig config = new JSONRPCTransportConfig();
- * config.setParameters(Map.of(
- *     OpenTelemetryClientTransportFactory.OTEL_TRACER_KEY,
- *     openTelemetry.getTracer("my-service"),
- *     OpenTelemetryClientTransportFactory.OTEL_OPEN_TELEMETRY_KEY,
- *     openTelemetry
- * ));
- * }
- */ -public class OpenTelemetryClientTransportWrapper implements ClientTransportWrapper { - - /** - * Configuration key for the OpenTelemetry Tracer instance. - * Value must be of type {@link Tracer}. - */ - public static final String OTEL_TRACER_KEY = "io.a2a.extras.opentelemetry.Tracer"; - - @Override - public ClientTransport wrap(ClientTransport transport, ClientTransportConfig config) { - Object tracerObj = config.getParameters().get(OTEL_TRACER_KEY); - if (tracerObj != null && tracerObj instanceof Tracer tracer) { - return new OpenTelemetryClientTransport(transport, tracer); - } - // No tracer configured, return unwrapped transport - return transport; - } - - @Override - public int priority() { - // Observability/tracing should be in the middle priority range - // so it can observe other wrappers but doesn't interfere with security - return 600; - } -} diff --git a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java b/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java deleted file mode 100644 index 0a7d54541..000000000 --- a/extras/opentelemetry/client/src/main/java/io/a2a/extras/opentelemetry/client/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.extras.opentelemetry.client; - -import org.jspecify.annotations.NullMarked; - diff --git a/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper b/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper deleted file mode 100644 index 801f7dd3a..000000000 --- a/extras/opentelemetry/client/src/main/resources/META-INF/services/io.a2a.client.transport.spi.ClientTransportWrapper +++ /dev/null @@ -1 +0,0 @@ -io.a2a.extras.opentelemetry.client.OpenTelemetryClientTransportWrapper diff --git a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java b/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java deleted file mode 100644 index 945ca84ad..000000000 --- a/extras/opentelemetry/client/src/test/java/io/a2a/extras/opentelemetry/client/OpenTelemetryClientTransportTest.java +++ /dev/null @@ -1,489 +0,0 @@ -package io.a2a.extras.opentelemetry.client; - -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; - -import io.a2a.client.transport.spi.ClientTransport; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TextPart; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Scope; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; - -import java.util.List; -import java.util.function.Consumer; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import io.a2a.spec.A2AMethods; - -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) -class OpenTelemetryClientTransportTest { - - @Mock - private ClientTransport delegate; - - @Mock - private Tracer tracer; - - @Mock - private SpanBuilder spanBuilder; - - @Mock - private Span span; - - @Mock - private Scope scope; - - @Mock - private SpanContext spanContext; - - @Mock - private ClientCallContext context; - - private OpenTelemetryClientTransport transport; - - @BeforeEach - void setUp() { - System.setProperty(EXTRACT_REQUEST_SYS_PROPERTY, "true"); - System.setProperty(EXTRACT_RESPONSE_SYS_PROPERTY, "true"); - when(tracer.spanBuilder(anyString())).thenReturn(spanBuilder); - when(spanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(spanBuilder); - when(spanBuilder.setAttribute(anyString(), anyString())).thenReturn(spanBuilder); - when(spanBuilder.setAttribute(anyString(), anyLong())).thenReturn(spanBuilder); - when(spanBuilder.addLink(any(SpanContext.class))).thenReturn(spanBuilder); - when(spanBuilder.startSpan()).thenReturn(span); - when(span.makeCurrent()).thenReturn(scope); - when(span.getSpanContext()).thenReturn(spanContext); - when(context.getHeaders()).thenReturn(new java.util.HashMap<>()); - - transport = new OpenTelemetryClientTransport(delegate, tracer); - } - - @Test - void testSendMessage_Success() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - EventKind expectedResult = mock(EventKind.class); - when(request.toString()).thenReturn("request-string"); - when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.sendMessage(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); - - EventKind result = transport.sendMessage(request, context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.SEND_MESSAGE_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.CLIENT); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setAttribute(GENAI_RESPONSE, "response-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - verify(scope).close(); - } - - @Test - void testSendMessage_NullResponse() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - when(request.toString()).thenReturn("request-string"); - when(delegate.sendMessage(eq(request), any(ClientCallContext.class))).thenReturn(null); - - EventKind result = transport.sendMessage(request, context); - - assertNull(result); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(spanBuilder, never()).setAttribute(eq(GENAI_RESPONSE), anyString()); - verify(span, never()).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testSendMessage_ThrowsException() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - when(request.toString()).thenReturn("request-string"); - A2AClientException expectedException = new A2AClientException("Test error"); - when(delegate.sendMessage(eq(request), any(ClientCallContext.class))).thenThrow(expectedException); - - A2AClientException exception = assertThrows(A2AClientException.class, - () -> transport.sendMessage(request, context)); - - assertEquals(expectedException, exception); - verify(span).setStatus(StatusCode.ERROR, "Test error"); - verify(span).end(); - verify(scope).close(); - } - - @Test - void testSendMessageStreaming() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - when(request.toString()).thenReturn("request-string"); - Consumer eventConsumer = mock(Consumer.class); - Consumer errorConsumer = mock(Consumer.class); - - transport.sendMessageStreaming(request, eventConsumer, errorConsumer, context); - - verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.CLIENT); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - - ArgumentCaptor> eventConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); - ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); - verify(delegate).sendMessageStreaming(eq(request), eventConsumerCaptor.capture(), - errorConsumerCaptor.capture(), any(ClientCallContext.class)); - - assertNotNull(eventConsumerCaptor.getValue()); - assertNotNull(errorConsumerCaptor.getValue()); - } - - @Test - void testGetTask_Success() throws A2AClientException { - TaskQueryParams request = mock(TaskQueryParams.class); - Task expectedResult = mock(Task.class); - when(request.toString()).thenReturn("request-string"); - when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.getTask(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); - - Task result = transport.getTask(request, context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.GET_TASK_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setAttribute(GENAI_RESPONSE, "response-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testCancelTask_Success() throws A2AClientException { - TaskIdParams request = mock(TaskIdParams.class); - Task expectedResult = mock(Task.class); - when(request.toString()).thenReturn("request-string"); - when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.cancelTask(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); - - Task result = transport.cancelTask(request, context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.CANCEL_TASK_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setAttribute(GENAI_RESPONSE, "response-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testListTasks_Success() throws A2AClientException { - ListTasksParams request = mock(ListTasksParams.class); - ListTasksResult expectedResult = mock(ListTasksResult.class); - when(request.toString()).thenReturn("request-string"); - when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.listTasks(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); - - ListTasksResult result = transport.listTasks(request, context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.LIST_TASK_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setAttribute(GENAI_RESPONSE, "response-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testCreateTaskPushNotificationConfiguration_Success() throws A2AClientException { - TaskPushNotificationConfig request = mock(TaskPushNotificationConfig.class); - TaskPushNotificationConfig expectedResult = mock(TaskPushNotificationConfig.class); - when(request.toString()).thenReturn("request-string"); - when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.createTaskPushNotificationConfiguration(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); - - TaskPushNotificationConfig result = transport.createTaskPushNotificationConfiguration(request, context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setAttribute(GENAI_RESPONSE, "response-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testGetTaskPushNotificationConfiguration_Success() throws A2AClientException { - GetTaskPushNotificationConfigParams request = mock(GetTaskPushNotificationConfigParams.class); - TaskPushNotificationConfig expectedResult = mock(TaskPushNotificationConfig.class); - when(request.toString()).thenReturn("request-string"); - when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.getTaskPushNotificationConfiguration(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); - - TaskPushNotificationConfig result = transport.getTaskPushNotificationConfiguration(request, context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setAttribute(GENAI_RESPONSE, "response-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testListTaskPushNotificationConfigurations_Success() throws A2AClientException { - ListTaskPushNotificationConfigParams request = mock(ListTaskPushNotificationConfigParams.class); - TaskPushNotificationConfig config1 = mock(TaskPushNotificationConfig.class); - TaskPushNotificationConfig config2 = mock(TaskPushNotificationConfig.class); - when(config1.toString()).thenReturn("config1"); - when(config2.toString()).thenReturn("config2"); - ListTaskPushNotificationConfigResult expectedResult = new ListTaskPushNotificationConfigResult(List.of(config1, config2)); - when(request.toString()).thenReturn("request-string"); - when(delegate.listTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class))).thenReturn(expectedResult); - - ListTaskPushNotificationConfigResult result = transport.listTaskPushNotificationConfigurations(request, context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.CLIENT); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setAttribute(GENAI_RESPONSE, "config1,config2"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testDeleteTaskPushNotificationConfigurations_Success() throws A2AClientException { - DeleteTaskPushNotificationConfigParams request = mock(DeleteTaskPushNotificationConfigParams.class); - when(request.toString()).thenReturn("request-string"); - doNothing().when(delegate).deleteTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class)); - - transport.deleteTaskPushNotificationConfigurations(request, context); - - verify(tracer).spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - verify(delegate).deleteTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class)); - } - - @Test - void testSubscribeToTask() throws A2AClientException { - TaskIdParams request = mock(TaskIdParams.class); - when(request.toString()).thenReturn("request-string"); - Consumer eventConsumer = mock(Consumer.class); - Consumer errorConsumer = mock(Consumer.class); - - transport.subscribeToTask(request, eventConsumer, errorConsumer, context); - - verify(tracer).spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.CLIENT); - verify(spanBuilder).setAttribute(GENAI_REQUEST, "request-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - - ArgumentCaptor> eventConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); - ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); - verify(delegate).subscribeToTask(eq(request), eventConsumerCaptor.capture(), - errorConsumerCaptor.capture(), any(ClientCallContext.class)); - - assertNotNull(eventConsumerCaptor.getValue()); - assertNotNull(errorConsumerCaptor.getValue()); - } - - @Test - void testGetAgentCard_Success() throws A2AClientException { - AgentCard expectedResult = mock(AgentCard.class); - when(expectedResult.toString()).thenReturn("response-string"); - when(delegate.getExtendedAgentCard(any(ClientCallContext.class))).thenReturn(expectedResult); - - AgentCard result = transport.getExtendedAgentCard(context); - - assertEquals(expectedResult, result); - verify(tracer).spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.CLIENT); - verify(span).setAttribute(GENAI_RESPONSE, "response-string"); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testGetAgentCard_NullResponse() throws A2AClientException { - when(delegate.getExtendedAgentCard(any(ClientCallContext.class))).thenReturn(null); - - AgentCard result = transport.getExtendedAgentCard(context); - - assertNull(result); - verify(tracer).spanBuilder(A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.CLIENT); - verify(span, never()).setAttribute(eq(GENAI_RESPONSE), anyString()); - verify(span, never()).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void testClose() { - transport.close(); - verify(delegate).close(); - } - - @Test - void testEventConsumer_ThroughSendMessageStreaming() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - when(request.toString()).thenReturn("request-string"); - - SpanBuilder eventSpanBuilder = mock(SpanBuilder.class); - Span eventSpan = mock(Span.class); - when(tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-event")).thenReturn(eventSpanBuilder); - when(eventSpanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(eventSpanBuilder); - when(eventSpanBuilder.setAttribute(anyString(), anyString())).thenReturn(eventSpanBuilder); - when(eventSpanBuilder.addLink(any(SpanContext.class))).thenReturn(eventSpanBuilder); - when(eventSpanBuilder.startSpan()).thenReturn(eventSpan); - - ArgumentCaptor> eventConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); - Consumer originalConsumer = mock(Consumer.class); - - transport.sendMessageStreaming(request, originalConsumer, mock(Consumer.class), context); - - verify(delegate).sendMessageStreaming(eq(request), eventConsumerCaptor.capture(), any(Consumer.class), any(ClientCallContext.class)); - - Message event = Message.builder() - .messageId("test-id") - .taskId("task-id") - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("test content"))) - .build(); - - eventConsumerCaptor.getValue().accept(event); - - verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-event"); - verify(eventSpan).setStatus(StatusCode.OK); - verify(eventSpan).end(); - verify(originalConsumer).accept(event); - } - - @Test - void testErrorConsumer_ThroughSendMessageStreaming() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - when(request.toString()).thenReturn("request-string"); - - SpanBuilder errorSpanBuilder = mock(SpanBuilder.class); - Span errorSpan = mock(Span.class); - when(tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-error")).thenReturn(errorSpanBuilder); - when(errorSpanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(errorSpanBuilder); - when(errorSpanBuilder.addLink(any(SpanContext.class))).thenReturn(errorSpanBuilder); - when(errorSpanBuilder.startSpan()).thenReturn(errorSpan); - - ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); - Consumer originalConsumer = mock(Consumer.class); - - transport.sendMessageStreaming(request, mock(Consumer.class), originalConsumer, context); - - verify(delegate).sendMessageStreaming(eq(request), any(Consumer.class), errorConsumerCaptor.capture(), any(ClientCallContext.class)); - - Throwable error = new RuntimeException("Test error"); - - errorConsumerCaptor.getValue().accept(error); - - verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD + "-error"); - verify(errorSpan).setStatus(StatusCode.ERROR, "Test error"); - verify(errorSpan).end(); - verify(originalConsumer).accept(error); - } - - @Test - void testErrorConsumer_WithNullThrowable() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - when(request.toString()).thenReturn("request-string"); - - ArgumentCaptor> errorConsumerCaptor = ArgumentCaptor.forClass(Consumer.class); - Consumer originalConsumer = mock(Consumer.class); - - transport.sendMessageStreaming(request, mock(Consumer.class), originalConsumer, context); - - verify(delegate).sendMessageStreaming(eq(request), any(Consumer.class), errorConsumerCaptor.capture(), any(ClientCallContext.class)); - - errorConsumerCaptor.getValue().accept(null); - - verify(originalConsumer, never()).accept(any()); - } - - @Test - void testDeleteTaskPushNotificationConfigurations_ThrowsException() throws A2AClientException { - DeleteTaskPushNotificationConfigParams request = mock(DeleteTaskPushNotificationConfigParams.class); - when(request.toString()).thenReturn("request-string"); - A2AClientException expectedException = new A2AClientException("Delete failed"); - doThrow(expectedException).when(delegate).deleteTaskPushNotificationConfigurations(eq(request), any(ClientCallContext.class)); - - A2AClientException exception = assertThrows(A2AClientException.class, - () -> transport.deleteTaskPushNotificationConfigurations(request, context)); - - assertEquals(expectedException, exception); - verify(span).setStatus(StatusCode.ERROR, "Delete failed"); - verify(span).end(); - } - - @Test - void testResubscribe_ThrowsException() throws A2AClientException { - TaskIdParams request = mock(TaskIdParams.class); - when(request.toString()).thenReturn("request-string"); - Consumer eventConsumer = mock(Consumer.class); - Consumer errorConsumer = mock(Consumer.class); - A2AClientException expectedException = new A2AClientException("Resubscribe failed"); - doThrow(expectedException).when(delegate).subscribeToTask(any(TaskIdParams.class), any(Consumer.class), - any(Consumer.class), any(ClientCallContext.class)); - - A2AClientException exception = assertThrows(A2AClientException.class, - () -> transport.subscribeToTask(request, eventConsumer, errorConsumer, context)); - - assertEquals(expectedException, exception); - verify(span).setStatus(StatusCode.ERROR, "Resubscribe failed"); - verify(span).end(); - } - - @Test - void testSendMessageStreaming_ThrowsException() throws A2AClientException { - MessageSendParams request = mock(MessageSendParams.class); - when(request.toString()).thenReturn("request-string"); - Consumer eventConsumer = mock(Consumer.class); - Consumer errorConsumer = mock(Consumer.class); - A2AClientException expectedException = new A2AClientException("Streaming failed"); - doThrow(expectedException).when(delegate).sendMessageStreaming(any(MessageSendParams.class), any(Consumer.class), - any(Consumer.class), any(ClientCallContext.class)); - - A2AClientException exception = assertThrows(A2AClientException.class, - () -> transport.sendMessageStreaming(request, eventConsumer, errorConsumer, context)); - - assertEquals(expectedException, exception); - verify(span).setStatus(StatusCode.ERROR, "Streaming failed"); - verify(span).end(); - } -} diff --git a/extras/opentelemetry/common/pom.xml b/extras/opentelemetry/common/pom.xml deleted file mode 100644 index 41d3f50eb..000000000 --- a/extras/opentelemetry/common/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-java-sdk-opentelemetry-common - - A2A Java SDK :: Extras :: Opentelemetry :: Common - Common OpenTelemetry utilities for A2A Java SDK - - diff --git a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java b/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java deleted file mode 100644 index c2821d8a7..000000000 --- a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/A2AObservabilityNames.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.a2a.extras.opentelemetry; - -public interface A2AObservabilityNames { - - String EXTRACT_REQUEST_SYS_PROPERTY = "io.a2a.server.extract.request"; - String EXTRACT_RESPONSE_SYS_PROPERTY = "io.a2a.server.extract.response"; - - String ERROR_TYPE = "error.type"; - - String GENAI_PREFIX = "gen_ai.agent.a2a"; - String GENAI_CONFIG_ID = GENAI_PREFIX + ".config_id"; - String GENAI_CONTEXT_ID = GENAI_PREFIX + ".context_id"; //gen_ai.conversation.id - String GENAI_EXTENSIONS = GENAI_PREFIX + ".extensions"; - String GENAI_MESSAGE_ID = GENAI_PREFIX + ".message_id"; - String GENAI_OPERATION_NAME = GENAI_PREFIX + ".operation.name"; //gen_ai.agent.operation.name ? - String GENAI_PARTS_NUMBER = GENAI_PREFIX + ".parts.number"; - String GENAI_PROTOCOL = GENAI_PREFIX + ".protocol"; - String GENAI_STATUS = GENAI_PREFIX + ".status"; - String GENAI_REQUEST = GENAI_PREFIX + ".request"; //gen_ai.input.messages ? - String GENAI_RESPONSE = GENAI_PREFIX + ".response"; // gen_ai.output.messages ? - String GENAI_ROLE = GENAI_PREFIX + ".role"; - String GENAI_TASK_ID = GENAI_PREFIX + ".task_id"; -} diff --git a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java b/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java deleted file mode 100644 index 8e7125631..000000000 --- a/extras/opentelemetry/common/src/main/java/io/a2a/extras/opentelemetry/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Common OpenTelemetry utilities and shared components for A2A Java SDK. - *

- * This package contains common utilities, constants, and helper classes - * used across both client and server OpenTelemetry integrations. - */ -@org.jspecify.annotations.NullMarked -package io.a2a.extras.opentelemetry; diff --git a/extras/opentelemetry/integration-tests/README.md b/extras/opentelemetry/integration-tests/README.md deleted file mode 100644 index a66fe8f6c..000000000 --- a/extras/opentelemetry/integration-tests/README.md +++ /dev/null @@ -1,160 +0,0 @@ -# OpenTelemetry Integration Tests (Quarkus-based) - -## Overview - -This module provides **Quarkus-based integration tests** for OpenTelemetry tracing in the A2A Java SDK, similar to the approach used in the [Quarkus OpenTelemetry quickstart](https://github.com/quarkusio/quarkus/tree/main/integration-tests/opentelemetry-quickstart). - -Unlike the previous mock-based tests, these are **real integration tests** that: -- Start an actual Quarkus application -- Expose a REST API with A2A agent endpoints -- Make real HTTP requests -- Validate that OpenTelemetry spans are created correctly - -## Architecture - -### Components - -1. **SimpleAgent** - A basic A2A agent implementation for testing - - Implements all RequestHandler methods - - Stores tasks in memory - - Provides simple echo responses for messages - -2. **AgentResource** - JAX-RS REST resource - - Exposes HTTP endpoints (`/a2a/tasks`, `/a2a/messages`, etc.) - - Delegates to the RequestHandler - - Creates ServerCallContext for each request - -3. **InstrumentedRequestHandler** - CDI Alternative - - Wraps SimpleAgent with OpenTelemetry decorator - - Delegates to the OpenTelemetry decorator for span creation - - Ensures spans are created for each operation - -4. **OpenTelemetryProducer** - CDI bean producer - - Creates the Tracer from Quarkus OpenTelemetry - - Produces the OpenTelemetryRequestHandlerDecorator (CDI decorator) - - Integrates with Quarkus OpenTelemetry extension - -## Test Strategy - -### Functional Tests (`OpenTelemetryIntegrationTest`) -- Use `@QuarkusTest` annotation -- Make real HTTP requests using REST Assured -- Verify HTTP responses are correct -- Ensure the application behaves correctly end-to-end - -### Tracing Tests (`OpenTelemetryTracingTest`) -- Use `InMemorySpanExporter` to capture spans -- Verify that HTTP requests create OpenTelemetry spans -- Validate span names, kinds (CLIENT/SERVER), and status codes -- Check that spans are properly ended - -## Current Status - -### ✅ Completed -- Project structure and POM configuration -- Quarkus dependencies and plugins (including opentelemetry-sdk-testing) -- SimpleAgentExecutor following reference module pattern -- TestAgentCardProducer with proper JSONRPC interface -- InMemorySpanExporter producer for span validation -- OpenTelemetryIntegrationTest using Client API -- Tests compile and run (service loader issues resolved) - -### 🔨 In Progress / Known Issues - -1. **Test Execution Timeouts** - - Tests are timing out during message send operations - - Error: "Timeout waiting for consumption to complete for task test-task-1" - - Likely a configuration issue between client (non-streaming) and server (streaming capable) - - Need to investigate JSONRPC transport configuration - -2. **Span Validation** - - InMemorySpanExporter is configured but needs verification - - Some tests are not finding expected spans - - May need to configure span processor to route to InMemorySpanExporter - -## Running the Tests - -### Prerequisites -```bash -# Build all A2A SDK modules first -mvn clean install -DskipTests -``` - -### Run Integration Tests -```bash -# From the integration-tests directory -mvn clean verify - -# Or from the root -mvn verify -pl extras/opentelemetry/integration-tests -am -``` - -### Run Specific Test -```bash -mvn test -Dtest=OpenTelemetryIntegrationTest -``` - -## Configuration - -### Application Properties -- `src/main/resources/application.properties` - Runtime configuration -- `src/test/resources/application.properties` - Test-specific configuration - -Key settings: -```properties -# OpenTelemetry -quarkus.otel.sdk.disabled=false -quarkus.otel.traces.enabled=true -quarkus.otel.service.name=a2a-opentelemetry-integration-test - -# Test mode: use in-memory exporter -quarkus.otel.traces.exporter=none -``` - -### beans.xml -Located at `src/main/resources/META-INF/beans.xml`: -- Enables CDI bean discovery -- Configures alternatives (InstrumentedRequestHandler) - -## Next Steps - -To complete this integration test module: - -1. **Resolve CDI ambiguity** - - Add `@Named` or custom qualifier to SimpleAgent - - Or exclude DefaultRequestHandler from test classpath - - Or use `@Alternative` more effectively - -2. **Configure span exporter** - - Properly wire InMemorySpanExporter into Quarkus OpenTelemetry - - May need custom OTel SDK configuration - -3. **Add more test scenarios** - - Test error handling and error spans - - Test streaming operations - - Test context propagation across services - - Test span attributes and metadata - -4. **Performance testing** (optional) - - Measure overhead of OpenTelemetry instrumentation - - Verify spans don't impact performance significantly - -## Comparison with Quarkus Quickstart - -This implementation follows the same patterns as the Quarkus OpenTelemetry quickstart: -- ✅ Uses `@QuarkusTest` for integration tests -- ✅ Uses REST Assured for HTTP testing -- ✅ Integrates with Quarkus OpenTelemetry extension -- ✅ Uses in-memory span exporter for validation -- ✅ Tests actual HTTP requests, not mocks - -Unlike the quickstart which is a standalone app, this module: -- Tests A2A SDK-specific functionality -- Validates OpenTelemetry CDI decorator integration -- Focuses on A2A protocol operations (tasks, messages, etc.) - -## References - -- [Quarkus OpenTelemetry Guide](https://quarkus.io/guides/opentelemetry) -- [Quarkus OpenTelemetry Quickstart](https://github.com/quarkusio/quarkus/tree/main/integration-tests/opentelemetry-quickstart) -- [OpenTelemetry Java Documentation](https://opentelemetry.io/docs/languages/java/) diff --git a/extras/opentelemetry/integration-tests/pom.xml b/extras/opentelemetry/integration-tests/pom.xml deleted file mode 100644 index 14ea7f8f9..000000000 --- a/extras/opentelemetry/integration-tests/pom.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-java-sdk-opentelemetry-integration-tests - - A2A Java SDK :: Extras :: OpenTelemetry :: Integration Tests - Quarkus-based integration tests for OpenTelemetry support in A2A Java SDK - - - - - ${project.groupId} - a2a-java-sdk-client - - - ${project.groupId} - a2a-java-sdk-reference-jsonrpc - - - ${project.groupId} - a2a-java-sdk-opentelemetry-server - - - ${project.groupId} - a2a-java-sdk-opentelemetry-client - - - - - io.quarkus - quarkus-opentelemetry - - - - - io.quarkus - quarkus-reactive-routes - - - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - - - com.google.code.gson - gson - - - - - io.quarkus - quarkus-junit5 - test - - - io.opentelemetry - opentelemetry-sdk-testing - - - io.rest-assured - rest-assured - test - - - org.awaitility - awaitility - test - - - - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - generate-code - generate-code-tests - - - - - --add-opens=java.base/java.lang=ALL-UNNAMED - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.jboss.logmanager.LogManager - ${maven.home} - - --add-opens java.base/java.lang=ALL-UNNAMED - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - integration-test - verify - - - - - - org.jboss.logmanager.LogManager - ${maven.home} - - --add-opens java.base/java.lang=ALL-UNNAMED - - - - - - diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java deleted file mode 100644 index f6f84f6e1..000000000 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/A2ATestRoutes.java +++ /dev/null @@ -1,228 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - - - -import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Scope; -import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; -import io.opentelemetry.sdk.trace.data.SpanData; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Param; -import io.quarkus.vertx.web.Route; -import io.vertx.ext.web.RoutingContext; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Test routes for OpenTelemetry integration testing. - * Exposes test utilities via REST endpoints. - */ -@Singleton -public class A2ATestRoutes { - - private static final String APPLICATION_JSON = "application/json"; - private static final String TEXT_PLAIN = "text/plain"; - private static final Gson gson = new GsonBuilder().create(); - - @Inject - TestUtilsBean testUtilsBean; - @Inject - InMemorySpanExporter inMemorySpanExporter; - - @Inject - Tracer tracer; - - @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void saveTask(@Body String body, RoutingContext rc) { - try { - Task task = JsonUtil.fromJson(body, Task.class); - testUtilsBean.saveTask(task); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void getTask(@Param String taskId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - rc.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) - .end(JsonUtil.toJson(task)); - - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTask(@Param String taskId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - testUtilsBean.deleteTask(taskId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) - public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { - try { - testUtilsBean.ensureQueue(taskId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { - try { - TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { - try { - TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getChildQueueCount(@Param String taskId, RoutingContext rc) { - int count = testUtilsBean.getChildQueueCount(taskId); - rc.response() - .setStatusCode(200) - .end(String.valueOf(count)); - } - - @Route(path = "/hello", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void hello(RoutingContext rc) { - Span span = tracer.spanBuilder("hello").startSpan(); - try (Scope scope = span.makeCurrent()) { - rc.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, TEXT_PLAIN) - .end("Hello from Quarkus REST"); - } finally { - span.end(); - } - } - - @Route(path = "/export", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}) - public void exportSpans(@Param String taskId, RoutingContext rc) { - List spans = inMemorySpanExporter.getFinishedSpanItems() - .stream() - .filter(sd -> !sd.getName().contains("export") && !sd.getName().contains("reset")) - .collect(Collectors.toList()); - String json = gson.toJson(serialize(spans)); - rc.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) - .end(json); - } - - private JsonElement serialize(List spanDatas) { - JsonArray spans = new JsonArray(spanDatas.size()); - for (SpanData spanData : spanDatas) { - JsonObject jsonObject = new JsonObject(); - - jsonObject.addProperty("spanId", spanData.getSpanId()); - jsonObject.addProperty("traceId", spanData.getTraceId()); - jsonObject.addProperty("name", spanData.getName()); - jsonObject.addProperty("kind", spanData.getKind().name()); - jsonObject.addProperty("ended", spanData.hasEnded()); - - jsonObject.addProperty("parentSpanId", spanData.getParentSpanContext().getSpanId()); - jsonObject.addProperty("parent_spanId", spanData.getParentSpanContext().getSpanId()); - jsonObject.addProperty("parent_traceId", spanData.getParentSpanContext().getTraceId()); - jsonObject.addProperty("parent_remote", spanData.getParentSpanContext().isRemote()); - jsonObject.addProperty("parent_valid", spanData.getParentSpanContext().isValid()); - - spanData.getAttributes().forEach((k, v) -> { - jsonObject.addProperty("attr_" + k.getKey(), v.toString()); - }); - - spanData.getResource().getAttributes().forEach((k, v) -> { - jsonObject.addProperty("resource_" + k.getKey(), v.toString()); - }); - spans.add(jsonObject); - } - - return spans; - } - - @Route(path = "/reset", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void reset(@Param String taskId, RoutingContext rc) { - inMemorySpanExporter.reset(); - rc.response().setStatusCode(200).end(); - } - - private void errorResponse(Throwable t, RoutingContext rc) { - t.printStackTrace(); - rc.response() - .setStatusCode(500) - .putHeader(CONTENT_TYPE, TEXT_PLAIN) - .end(); - } - - @ApplicationScoped - static class InMemorySpanExporterProducer { - - @Produces - @Singleton - InMemorySpanExporter inMemorySpanExporter() { - return InMemorySpanExporter.create(); - } - } -} diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java deleted file mode 100644 index 6d33dd89c..000000000 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/SimpleAgentExecutor.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import io.a2a.A2A; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.TextPart; -import jakarta.enterprise.context.ApplicationScoped; - -/** - * Simple AgentExecutor for integration testing. - * Echoes back the user's message and completes the task immediately. - */ -@ApplicationScoped -public class SimpleAgentExecutor implements AgentExecutor { - - @Override - public void execute(RequestContext context, AgentEmitter emitter) throws A2AError { - // If task doesn't exist, create it - if (context.getTask() == null) { - emitter.submit(); - } - - // Get the user's message - String userText = context.getMessage().parts().stream() - .filter(part -> part instanceof TextPart) - .map(part -> ((TextPart) part).text()) - .findFirst() - .orElse(""); - - // Echo it back - String response = "Echo: " + userText; - emitter.complete(A2A.toAgentMessage(response)); - } - - @Override - public void cancel(RequestContext context, AgentEmitter emitter) throws A2AError { - emitter.cancel(); - } -} diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java deleted file mode 100644 index 373169fac..000000000 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestAgentCardProducer.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import java.util.Collections; -import java.util.List; - - -/** - * Produces the AgentCard for integration testing. - */ -@ApplicationScoped -public class TestAgentCardProducer { - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return AgentCard.builder() - .name("OpenTelemetry Test Agent") - .description("Test agent for OpenTelemetry integration tests") - .supportedInterfaces(Collections.singletonList( - new AgentInterface("JSONRPC", "http://localhost:8081") - )) - .version("1.0.0-TEST") - .documentationUrl("http://example.com/test") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(AgentSkill.builder() - .id("echo") - .name("Echo") - .description("Echoes back the user's message") - .tags(Collections.singletonList("test")) - .examples(List.of("hello", "test message")) - .build())) - .build(); - } -} diff --git a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java b/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java deleted file mode 100644 index 594063171..000000000 --- a/extras/opentelemetry/integration-tests/src/main/java/io/a2a/extras/opentelemetry/it/TestUtilsBean.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Event; -import io.a2a.spec.Task; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -/** - * Test utilities for OpenTelemetry integration tests. - * Allows direct manipulation of tasks and queues for testing. - */ -@ApplicationScoped -public class TestUtilsBean { - - @Inject - TaskStore taskStore; - - @Inject - QueueManager queueManager; - - public void saveTask(Task task) { - taskStore.save(task, false); - } - - public Task getTask(String taskId) { - return taskStore.get(taskId); - } - - public void deleteTask(String taskId) { - taskStore.delete(taskId); - } - - public void ensureQueue(String taskId) { - queueManager.createOrTap(taskId); - } - - public void enqueueEvent(String taskId, Event event) { - queueManager.get(taskId).enqueueEvent(event); - } - - public int getChildQueueCount(String taskId) { - return queueManager.getActiveChildQueueCount(taskId); - } -} diff --git a/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml b/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 5badbc80d..000000000 --- a/extras/opentelemetry/integration-tests/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - io.a2a.extras.opentelemetry.it.InstrumentedRequestHandler - - diff --git a/extras/opentelemetry/integration-tests/src/main/resources/application.properties b/extras/opentelemetry/integration-tests/src/main/resources/application.properties deleted file mode 100644 index ca0d2c4fd..000000000 --- a/extras/opentelemetry/integration-tests/src/main/resources/application.properties +++ /dev/null @@ -1,28 +0,0 @@ -# Quarkus configuration -quarkus.application.name=a2a-otel-test - -# HTTP configuration -quarkus.http.port=8081 -quarkus.http.test-port=8081 - -# OpenTelemetry configuration -quarkus.otel.sdk.disabled=false -quarkus.otel.traces.enabled=true -quarkus.otel.metrics.enabled=false -quarkus.otel.logs.enabled=false - -quarkus.otel.instrument.vertx-http=false - -quarkus.otel.bsp.schedule.delay=0 -quarkus.otel.bsp.export.timeout=5s - -# Service name -quarkus.otel.service.name=a2a-opentelemetry-integration-test - -# Propagators -quarkus.otel.propagators=tracecontext - -# Logging -quarkus.log.level=INFO -quarkus.log.category."io.a2a".level=DEBUG -quarkus.log.category."io.opentelemetry".level=DEBUG diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java deleted file mode 100644 index 69304e10e..000000000 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/BaseTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import static io.restassured.RestAssured.get; - -import java.util.List; -import java.util.Map; - -import io.restassured.common.mapper.TypeRef; - -public class BaseTest { - - protected List> getSpans() { - return get("/export").body().as(new TypeRef<>() { - }); - } - - protected void buildGlobalTelemetryInstance() { - // Do nothing in JVM mode - } -} \ No newline at end of file diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java deleted file mode 100644 index 50c8c82ed..000000000 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ABaseTest.java +++ /dev/null @@ -1,301 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import static io.quarkus.vertx.web.ReactiveRoutes.APPLICATION_JSON; -import static io.restassured.RestAssured.given; -import static java.net.HttpURLConnection.HTTP_OK; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.*; - -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.*; -import io.opentelemetry.api.trace.SpanKind; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * Abstract base class for OpenTelemetry A2A integration tests. - * Contains common test logic shared between unit and integration test modes. - */ -abstract class OpenTelemetryA2ABaseTest extends BaseTest { - - protected Client client; - protected final int serverPort = 8081; - - @BeforeEach - void setUp() throws A2AClientException { - ClientConfig clientConfig = new ClientConfig.Builder() - .setStreaming(false) - .build(); - - client = Client.builder(A2A.getAgentCard("http://localhost:" + serverPort)) - .clientConfig(clientConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - } - - @BeforeEach - void reset() { - await().atMost(5, SECONDS).until(() -> { - List> spans = getSpans(); - if (spans.isEmpty()) { - return true; - } else { - given().get("/reset").then().statusCode(HTTP_OK); - return false; - } - }); - } - - @Test - void testGetTaskCreatesSpans() throws Exception { - String taskId = "span-test-task-1"; - String contextId = "span-test-ctx-1"; - - Task task = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - - saveTaskInTaskStore(task); - reset(); - - try { - Task retrievedTask = client.getTask(new TaskQueryParams(taskId), null); - - assertNotNull(retrievedTask); - assertEquals(taskId, retrievedTask.id()); - - Thread.sleep(5000); - - List> spans = getSpans(); - System.out.println("We have created spans " + spans); - assertFalse(spans.isEmpty(), "Should have created spans for getTask operation"); - - long serverSpanCount = spans.stream() - .filter(span -> SpanKind.valueOf((span.get("kind").toString())) == SpanKind.SERVER) - .count(); - assertTrue(serverSpanCount > 0, "Should have at least one SERVER span"); - - Map serverSpan = spans.stream() - .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) - .filter(span -> "GetTask".equals(span.get("name"))) - .findFirst() - .orElseThrow(() -> new AssertionError("No SERVER span found for GetTask")); - - assertEquals("GetTask", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), - "Operation name attribute should be set"); - assertEquals(taskId, serverSpan.get("attr_gen_ai.agent.a2a.task_id"), - "Task ID attribute should be set"); - - } finally { - deleteTaskInTaskStore(taskId); - } - } - - @Test - void testListTasksCreatesSpans() throws Exception { - reset(); - - ListTasksParams params = new ListTasksParams( - null, null, null, null, null, null, null, "" - ); - - io.a2a.jsonrpc.common.wrappers.ListTasksResult result = client.listTasks(params, null); - - assertNotNull(result); - - Thread.sleep(5000); - - List> spans = getSpans(); - System.out.println("We have created spans " + spans); - assertFalse(spans.isEmpty(), "Should have created spans for listTasks"); - - Map serverSpan = spans.stream() - .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) - .filter(span -> "ListTasks".equals(span.get("name"))) - .findFirst() - .orElseThrow(() -> new AssertionError("No SERVER span found for ListTasks")); - - assertEquals("ListTasks", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), - "Operation name attribute should be set"); - } - - @Test - void testCancelTaskCreatesSpans() throws Exception { - String taskId = "cancel-test-task-1"; - String contextId = "cancel-test-ctx-1"; - - Task task = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - - saveTaskInTaskStore(task); - ensureQueueForTask(taskId); - reset(); - - try { - Task cancelledTask = client.cancelTask(new TaskIdParams(taskId), null); - - assertNotNull(cancelledTask); - assertEquals(TaskState.TASK_STATE_CANCELED, cancelledTask.status().state()); - - Thread.sleep(5000); - - List> spans = getSpans(); - System.out.println("We have created spans " + spans); - assertFalse(spans.isEmpty(), "Should have created spans for cancelTask"); - - Map serverSpan = spans.stream() - .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) - .filter(span -> "CancelTask".equals(span.get("name"))) - .findFirst() - .orElseThrow(() -> new AssertionError("No SERVER span found for CancelTask")); - - assertEquals("CancelTask", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), - "Operation name attribute should be set"); - assertEquals(taskId, serverSpan.get("attr_gen_ai.agent.a2a.task_id"), - "Task ID attribute should be set"); - - } finally { - deleteTaskInTaskStore(taskId); - } - } - - @Test - void testSpanAttributes() throws Exception { - String taskId = "attr-test-task-1"; - String contextId = "attr-test-ctx-1"; - - Task task = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - - saveTaskInTaskStore(task); - reset(); - - try { - client.getTask(new TaskQueryParams(taskId), null); - - Thread.sleep(5000); - - List> spans = getSpans(); - System.out.println("We have created spans " + spans); - assertFalse(spans.isEmpty()); - - Map serverSpan = spans.stream() - .filter(span -> SpanKind.valueOf(span.get("kind").toString()) == SpanKind.SERVER) - .filter(span -> "GetTask".equals(span.get("name"))) - .findFirst() - .orElseThrow(() -> new AssertionError("No SERVER span found for GetTask")); - - assertNotNull(serverSpan.get("spanId"), "Span should have a span ID"); - assertNotNull(serverSpan.get("traceId"), "Span should have a trace ID"); - assertEquals("GetTask", serverSpan.get("name"), "Span name should be GetTask"); - assertEquals("SERVER", serverSpan.get("kind"), "Span kind should be SERVER"); - assertEquals(Boolean.TRUE, serverSpan.get("ended"), "Span should be ended"); - - assertEquals("GetTask", serverSpan.get("attr_gen_ai.agent.a2a.operation.name"), - "Operation name attribute should be set"); - assertEquals(taskId, serverSpan.get("attr_gen_ai.agent.a2a.task_id"), - "Task ID attribute should be set"); - - assertNotNull(serverSpan.get("resource_service.name"), - "Service name resource attribute should be set"); - System.out.println("Service name: " + serverSpan.get("resource_service.name")); - - assertNotNull(serverSpan.get("parentSpanId"), "Span should have parent span ID field"); - - } finally { - deleteTaskInTaskStore(taskId); - } - } - - protected void saveTaskInTaskStore(Task task) throws Exception { - HttpClient httpClient = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/task")) - .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(task))) - .header("Content-Type", APPLICATION_JSON) - .build(); - - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(String.format("Saving task failed! Status: %d, Body: %s", response.statusCode(), response.body())); - } - } - - protected Task getTaskFromTaskStore(String taskId) throws Exception { - HttpClient httpClient = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) - .GET() - .build(); - - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() == 404) { - return null; - } - if (response.statusCode() != 200) { - throw new RuntimeException(String.format("Getting task failed! Status: %d, Body: %s", response.statusCode(), response.body())); - } - return JsonUtil.fromJson(response.body(), Task.class); - } - - protected void deleteTaskInTaskStore(String taskId) throws Exception { - HttpClient httpClient = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(("http://localhost:" + serverPort + "/test/task/" + taskId))) - .DELETE() - .build(); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(response.statusCode() + ": Deleting task failed!" + response.body()); - } - } - - protected void ensureQueueForTask(String taskId) throws Exception { - HttpClient httpClient = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/queue/ensure/" + taskId)) - .POST(HttpRequest.BodyPublishers.noBody()) - .build(); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(String.format("Ensuring queue failed! Status: %d, Body: %s", response.statusCode(), response.body())); - } - } -} diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java deleted file mode 100644 index 7701acd23..000000000 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2AIT.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import io.quarkus.test.junit.QuarkusIntegrationTest; - -/** - * Integration test for OpenTelemetry tracing in A2A SDK. - * Runs in native mode with @QuarkusIntegrationTest annotation. - */ -@QuarkusIntegrationTest -class OpenTelemetryA2AIT extends OpenTelemetryA2ABaseTest { -} diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java deleted file mode 100644 index d6c73b05c..000000000 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryA2ATest.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import io.quarkus.test.junit.QuarkusTest; - -/** - * Unit test for OpenTelemetry tracing in A2A SDK. - * Runs in JVM mode with @QuarkusTest annotation. - */ -@QuarkusTest -class OpenTelemetryA2ATest extends OpenTelemetryA2ABaseTest { -} diff --git a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java b/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java deleted file mode 100644 index 50011fa81..000000000 --- a/extras/opentelemetry/integration-tests/src/test/java/io/a2a/extras/opentelemetry/it/OpenTelemetryTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.a2a.extras.opentelemetry.it; - -import static io.restassured.RestAssured.given; -import static java.net.HttpURLConnection.HTTP_OK; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.awaitility.Awaitility.await; -import static org.hamcrest.CoreMatchers.is; - -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import io.quarkus.test.junit.QuarkusTest; - -@QuarkusTest -public class OpenTelemetryTest extends BaseTest { - - @BeforeEach - void reset() { - await().atMost(5, SECONDS).until(() -> { - List> spans = getSpans(); - if (spans.isEmpty()) { - return true; - } else { - given().get("/reset").then().statusCode(HTTP_OK); - return false; - } - }); - } - - @Test - void buildTimeEnabled() { - given() - .when().get("/hello") - .then() - .statusCode(200) - .body(is("Hello from Quarkus REST")); - await().atMost(5, SECONDS).until(() -> getSpans().size() == 1); - } -} \ No newline at end of file diff --git a/extras/opentelemetry/integration-tests/src/test/resources/application.properties b/extras/opentelemetry/integration-tests/src/test/resources/application.properties deleted file mode 100644 index 1e459ea8e..000000000 --- a/extras/opentelemetry/integration-tests/src/test/resources/application.properties +++ /dev/null @@ -1,25 +0,0 @@ -# Test configuration -quarkus.application.name=a2a-otel-test - -# HTTP configuration -quarkus.http.test-port=8081 - -# OpenTelemetry configuration for testing -quarkus.otel.sdk.disabled=false -quarkus.otel.traces.enabled=true -quarkus.otel.metrics.enabled=false -quarkus.otel.logs.enabled=false -quarkus.otel.instrument.vertx-http=false - -quarkus.otel.bsp.schedule.delay=0 -quarkus.otel.bsp.export.timeout=5s - -# Service name -quarkus.otel.service.name=a2a-opentelemetry-integration-test - -# Propagators -quarkus.otel.propagators=tracecontext - -# Logging -quarkus.log.level=INFO -quarkus.log.category."io.a2a".level=DEBUG diff --git a/extras/opentelemetry/pom.xml b/extras/opentelemetry/pom.xml deleted file mode 100644 index 0741ff55a..000000000 --- a/extras/opentelemetry/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-sdk-opentelemetry-parent - pom - - A2A Java SDK :: Extras :: Opentelemetry :: Parent - Java SDK for the Agent2Agent Protocol (A2A) - Extras - Opentelemetry - - - 2.0.1 - - - - org.eclipse.microprofile.telemetry - microprofile-telemetry-api - ${version.org.eclipse.microprofile.telemetry} - pom - provided - - - - - common - client-propagation - client - server - integration-tests - - - \ No newline at end of file diff --git a/extras/opentelemetry/server/pom.xml b/extras/opentelemetry/server/pom.xml deleted file mode 100644 index afc62d631..000000000 --- a/extras/opentelemetry/server/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-java-sdk-opentelemetry-server - - A2A Java SDK :: Extras :: Opentelemetry :: Server - OpenTelemetry server support for A2A Java SDK - - - - ${project.groupId} - a2a-java-sdk-opentelemetry-common - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - - - ${project.groupId} - a2a-java-sdk-spec-grpc - - - org.eclipse.microprofile.telemetry - microprofile-telemetry-api - ${version.org.eclipse.microprofile.telemetry} - pom - provided - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - org.slf4j - slf4j-api - - - org.junit.jupiter - junit-jupiter - test - - - org.mockito - mockito-core - test - - - org.mockito - mockito-junit-jupiter - test - - - - diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java deleted file mode 100644 index 93fa3f86f..000000000 --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecorator.java +++ /dev/null @@ -1,465 +0,0 @@ -package io.a2a.extras.opentelemetry; - -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONFIG_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_CONTEXT_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_EXTENSIONS; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_MESSAGE_ID; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_OPERATION_NAME; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_PARTS_NUMBER; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_ROLE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_TASK_ID; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.ServerCallContext; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AMethods; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Scope; -import jakarta.annotation.Priority; -import jakarta.decorator.Decorator; -import jakarta.decorator.Delegate; -import jakarta.enterprise.inject.Any; -import jakarta.inject.Inject; -import java.util.concurrent.Flow; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * OpenTelemetry CDI Decorator for {@link RequestHandler}. - *

- * This decorator adds distributed tracing to A2A server request handlers. - * It creates spans for each request handler method invocation, capturing: - *

    - *
  • Request parameters as span attributes
  • - *
  • Response data as span attributes
  • - *
  • Errors and exceptions with proper status codes
  • - *
  • Timing information for performance monitoring
  • - *
- *

- * To enable this decorator, add it to your beans.xml: - *

{@code
- * 
- *     io.a2a.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator
- * 
- * }
- */ -@Decorator -@Priority(100) -public abstract class OpenTelemetryRequestHandlerDecorator implements RequestHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(OpenTelemetryRequestHandlerDecorator.class); - - @Inject - @Delegate - @Any - private RequestHandler delegate; - - @Inject - private Tracer tracer; - - /** - * Default constructor for CDI. - */ - public OpenTelemetryRequestHandlerDecorator() { - } - - /** - * Constructor for testing. - * - * @param delegate the delegate request handler - * @param tracer the tracer to use - */ - public OpenTelemetryRequestHandlerDecorator(RequestHandler delegate, Tracer tracer) { - this.delegate = delegate; - this.tracer = tracer; - } - - @Override - public Task onGetTask(TaskQueryParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_METHOD); - - if (params.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - Task result = delegate.onGetTask(params, context); - - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_METHOD); - - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - if (params.contextId() != null) { - spanBuilder.setAttribute(GENAI_CONTEXT_ID, params.contextId()); - } - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - ListTasksResult result = delegate.onListTasks(params, context); - - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.CANCEL_TASK_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.CANCEL_TASK_METHOD); - - if (params.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - Task result = delegate.onCancelTask(params, context); - - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public EventKind onMessageSend(MessageSendParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.SEND_MESSAGE_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_MESSAGE_METHOD); - - if (params.message() != null) { - if (params.message().taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.message().taskId()); - } - if (params.message().contextId() != null) { - spanBuilder.setAttribute(GENAI_CONTEXT_ID, params.message().contextId()); - } - if (params.message().messageId() != null) { - spanBuilder.setAttribute(GENAI_MESSAGE_ID, params.message().messageId()); - } - if (params.message().role() != null) { - spanBuilder.setAttribute(GENAI_ROLE, params.message().role().name()); - } - if (params.message().extensions() != null && !params.message().extensions().isEmpty()) { - spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", params.message().extensions())); - } - spanBuilder.setAttribute(GENAI_PARTS_NUMBER, params.message().parts().size()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - EventKind result = delegate.onMessageSend(params, context); - - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public Flow.Publisher onMessageSendStream(MessageSendParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SEND_STREAMING_MESSAGE_METHOD); - - if (params.message() != null) { - if (params.message().taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.message().taskId()); - } - if (params.message().contextId() != null) { - spanBuilder.setAttribute(GENAI_CONTEXT_ID, params.message().contextId()); - } - if (params.message().messageId() != null) { - spanBuilder.setAttribute(GENAI_MESSAGE_ID, params.message().messageId()); - } - if (params.message().role() != null) { - spanBuilder.setAttribute(GENAI_ROLE, params.message().role().name()); - } - if (params.message().extensions() != null && !params.message().extensions().isEmpty()) { - spanBuilder.setAttribute(GENAI_EXTENSIONS, String.join(",", params.message().extensions())); - } - spanBuilder.setAttribute(GENAI_PARTS_NUMBER, params.message().parts().size()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - Flow.Publisher result = delegate.onMessageSendStream(params, context); - - if (extractResponse()) { - span.setAttribute(GENAI_RESPONSE, "Stream publisher created"); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public TaskPushNotificationConfig onCreateTaskPushNotificationConfig(TaskPushNotificationConfig params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - if (params.taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); - } - if (params.config() != null && params.config().id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, params.config().id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - TaskPushNotificationConfig result = delegate.onCreateTaskPushNotificationConfig(params, context); - - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public TaskPushNotificationConfig onGetTaskPushNotificationConfig(GetTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - if (params.taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); - } - if (params.id() != null) { - spanBuilder.setAttribute(GENAI_CONFIG_ID, params.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - TaskPushNotificationConfig result = delegate.onGetTaskPushNotificationConfig(params, context); - - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public Flow.Publisher onSubscribeToTask(TaskIdParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.SUBSCRIBE_TO_TASK_METHOD); - - if (params.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); - } - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - Flow.Publisher result = delegate.onSubscribeToTask(params, context); - - if (extractResponse()) { - span.setAttribute(GENAI_RESPONSE, "Stream publisher created"); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig(ListTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - if (params.id() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.id()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - ListTaskPushNotificationConfigResult result = delegate.onListTaskPushNotificationConfig(params, context); - - if (result != null && extractResponse()) { - span.setAttribute(GENAI_RESPONSE, result.toString()); - } - - span.setStatus(StatusCode.OK); - return result; - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - @Override - public void onDeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { - var spanBuilder = tracer.spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD) - .setSpanKind(SpanKind.SERVER) - .setAttribute(GENAI_OPERATION_NAME, A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - if (extractRequest()) { - spanBuilder.setAttribute(GENAI_REQUEST, params.toString()); - } - if (params.taskId() != null) { - spanBuilder.setAttribute(GENAI_TASK_ID, params.taskId()); - } - - Span span = spanBuilder.startSpan(); - - try (Scope scope = span.makeCurrent()) { - delegate.onDeleteTaskPushNotificationConfig(params, context); - - span.setStatus(StatusCode.OK); - } catch (A2AError error) { - span.setAttribute(ERROR_TYPE, error.getMessage()); - span.setStatus(StatusCode.ERROR, error.getMessage()); - throw error; - } finally { - span.end(); - } - } - - private boolean extractRequest() { - return Boolean.getBoolean(EXTRACT_REQUEST_SYS_PROPERTY); - } - - private boolean extractResponse() { - return Boolean.getBoolean(EXTRACT_RESPONSE_SYS_PROPERTY); - } -} diff --git a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java b/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java deleted file mode 100644 index fdd7057d5..000000000 --- a/extras/opentelemetry/server/src/main/java/io/a2a/extras/opentelemetry/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.extras.opentelemetry; - -import org.jspecify.annotations.NullMarked; - diff --git a/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml b/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml deleted file mode 100644 index dcc4135c8..000000000 --- a/extras/opentelemetry/server/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - io.a2a.extras.opentelemetry.OpenTelemetryRequestHandlerDecorator - - \ No newline at end of file diff --git a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java b/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java deleted file mode 100644 index 4378fdbb8..000000000 --- a/extras/opentelemetry/server/src/test/java/io/a2a/extras/opentelemetry/OpenTelemetryRequestHandlerDecoratorTest.java +++ /dev/null @@ -1,497 +0,0 @@ -package io.a2a.extras.opentelemetry; - -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.ERROR_TYPE; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_REQUEST_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.EXTRACT_RESPONSE_SYS_PROPERTY; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_REQUEST; -import static io.a2a.extras.opentelemetry.A2AObservabilityNames.GENAI_RESPONSE; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.ServerCallContext; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.spec.*; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanBuilder; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Scope; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Flow; - -@ExtendWith(MockitoExtension.class) -class OpenTelemetryRequestHandlerDecoratorTest { - - @Mock - private Tracer tracer; - - @Mock - private Span span; - - @Mock - private SpanBuilder spanBuilder; - - @Mock - private Scope scope; - - @Mock - private ServerCallContext context; - - @Mock - private RequestHandler delegate; - - private TestableOpenTelemetryRequestHandlerDecorator decorator; - - @BeforeEach - void setUp() { - // Set system properties for extracting request/response - System.setProperty(EXTRACT_REQUEST_SYS_PROPERTY, "true"); - System.setProperty(EXTRACT_RESPONSE_SYS_PROPERTY, "true"); - - // Set up the mock chain - lenient().when(tracer.spanBuilder(anyString())).thenReturn(spanBuilder); - lenient().when(spanBuilder.setSpanKind(any(SpanKind.class))).thenReturn(spanBuilder); - lenient().when(spanBuilder.setAttribute(anyString(), anyString())).thenReturn(spanBuilder); - lenient().when(spanBuilder.setAttribute(anyString(), anyLong())).thenReturn(spanBuilder); - lenient().when(spanBuilder.startSpan()).thenReturn(span); - lenient().when(span.makeCurrent()).thenReturn(scope); - lenient().when(span.setAttribute(anyString(), anyString())).thenReturn(span); - lenient().when(span.setStatus(any(StatusCode.class))).thenReturn(span); - lenient().when(span.setStatus(any(StatusCode.class), anyString())).thenReturn(span); - - // Create decorator with mocked dependencies - decorator = new TestableOpenTelemetryRequestHandlerDecorator(delegate, tracer); - } - - /** - * Concrete test implementation of the abstract decorator for testing purposes. - */ - static class TestableOpenTelemetryRequestHandlerDecorator extends OpenTelemetryRequestHandlerDecorator { - public TestableOpenTelemetryRequestHandlerDecorator(RequestHandler delegate, Tracer tracer) { - super(delegate, tracer); - } - } - - @Nested - class GetTaskTests { - @Test - void onGetTask_createsSpanAndDelegatesToHandler() throws A2AError { - TaskQueryParams params = new TaskQueryParams("task-123", null); - Task result = Task.builder() - .id("task-123") - .contextId("ctx-1") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - when(delegate.onGetTask(params, context)).thenReturn(result); - - Task actualResult = decorator.onGetTask(params, context); - - assertEquals(result, actualResult); - verify(tracer).spanBuilder(A2AMethods.GET_TASK_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.SERVER); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(spanBuilder).startSpan(); - verify(span).makeCurrent(); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - verify(delegate).onGetTask(params, context); - } - - @Test - void onGetTask_withError_setsErrorStatusAndRethrows() throws A2AError { - TaskQueryParams params = new TaskQueryParams("task-123", null); - A2AError error = new TaskNotFoundError(); - when(delegate.onGetTask(params, context)).thenThrow(error); - - assertThrows(TaskNotFoundError.class, () -> decorator.onGetTask(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class ListTasksTests { - @Test - void onListTasks_createsSpanAndDelegatesToHandler() throws A2AError { - ListTasksParams params = new ListTasksParams(null, null, null, null, null, null, null, "test-tenant"); - ListTasksResult result = new ListTasksResult(Collections.emptyList(), 0, 0, null); - when(delegate.onListTasks(params, context)).thenReturn(result); - - ListTasksResult actualResult = decorator.onListTasks(params, context); - - assertEquals(result, actualResult); - verify(tracer).spanBuilder(A2AMethods.LIST_TASK_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void onListTasks_withError_setsErrorStatus() throws A2AError { - ListTasksParams params = new ListTasksParams(null, null, null, null, null, null, null, "test-tenant"); - A2AError error = new InvalidRequestError("Invalid parameters"); - when(delegate.onListTasks(params, context)).thenThrow(error); - - assertThrows(InvalidRequestError.class, () -> decorator.onListTasks(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class CancelTaskTests { - @Test - void onCancelTask_createsSpanAndDelegatesToHandler() throws A2AError { - TaskIdParams params = new TaskIdParams("task-123"); - Task result = Task.builder() - .id("task-123") - .contextId("ctx-1") - .status(new TaskStatus(TaskState.TASK_STATE_CANCELED)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - when(delegate.onCancelTask(params, context)).thenReturn(result); - - Task actualResult = decorator.onCancelTask(params, context); - - assertEquals(result, actualResult); - verify(tracer).spanBuilder(A2AMethods.CANCEL_TASK_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void onCancelTask_withError_setsErrorStatus() throws A2AError { - TaskIdParams params = new TaskIdParams("task-123"); - A2AError error = new TaskNotFoundError(); - when(delegate.onCancelTask(params, context)).thenThrow(error); - - assertThrows(TaskNotFoundError.class, () -> decorator.onCancelTask(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class MessageSendTests { - @Test - void onMessageSend_createsSpanAndDelegatesToHandler() throws A2AError { - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("test message"))) - .messageId("msg-123") - .contextId("ctx-1") - .taskId("task-123") - .build(); - MessageSendParams params = new MessageSendParams(message, null, null, ""); - EventKind result = Task.builder() - .id("task-123") - .contextId("ctx-1") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - when(delegate.onMessageSend(params, context)).thenReturn(result); - - EventKind actualResult = decorator.onMessageSend(params, context); - - assertEquals(result, actualResult); - verify(tracer).spanBuilder(A2AMethods.SEND_MESSAGE_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - } - - @Test - void onMessageSend_withError_setsErrorStatus() throws A2AError { - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("test message"))) - .messageId("msg-123") - .contextId("ctx-1") - .taskId("task-123") - .build(); - MessageSendParams params = new MessageSendParams(message, null, null, ""); - A2AError error = new InvalidRequestError("Invalid message"); - when(delegate.onMessageSend(params, context)).thenThrow(error); - - assertThrows(InvalidRequestError.class, () -> decorator.onMessageSend(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class MessageSendStreamTests { - @Test - void onMessageSendStream_createsSpanWithSpecialMessage() throws A2AError { - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("test message"))) - .messageId("msg-123") - .contextId("ctx-1") - .taskId("task-123") - .build(); - MessageSendParams params = new MessageSendParams(message, null, null, ""); - Flow.Publisher publisher = mock(Flow.Publisher.class); - when(delegate.onMessageSendStream(params, context)).thenReturn(publisher); - - Flow.Publisher actualResult = decorator.onMessageSendStream(params, context); - - assertEquals(publisher, actualResult); - verify(tracer).spanBuilder(A2AMethods.SEND_STREAMING_MESSAGE_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, "Stream publisher created"); - verify(span).setStatus(StatusCode.OK); - } - - @Test - void onMessageSendStream_withError_setsErrorStatus() throws A2AError { - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("test message"))) - .messageId("msg-123") - .contextId("ctx-1") - .taskId("task-123") - .build(); - MessageSendParams params = new MessageSendParams(message, null, null, ""); - A2AError error = new InvalidRequestError("Stream error"); - when(delegate.onMessageSendStream(params, context)).thenThrow(error); - - assertThrows(InvalidRequestError.class, () -> decorator.onMessageSendStream(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class SetTaskPushNotificationConfigTests { - @Test - void onSetTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { - PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); - TaskPushNotificationConfig params = new TaskPushNotificationConfig("task-123", config, null); - TaskPushNotificationConfig result = new TaskPushNotificationConfig("task-123", config, null); - when(delegate.onCreateTaskPushNotificationConfig(params, context)).thenReturn(result); - - TaskPushNotificationConfig actualResult = decorator.onCreateTaskPushNotificationConfig(params, context); - - assertEquals(result, actualResult); - verify(tracer).spanBuilder(A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void onSetTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { - PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); - TaskPushNotificationConfig params = new TaskPushNotificationConfig("task-123", config, null); - A2AError error = new InvalidRequestError("Invalid config"); - when(delegate.onCreateTaskPushNotificationConfig(params, context)).thenThrow(error); - - assertThrows(InvalidRequestError.class, () -> decorator.onCreateTaskPushNotificationConfig(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class GetTaskPushNotificationConfigTests { - @Test - void onGetTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { - GetTaskPushNotificationConfigParams params = new GetTaskPushNotificationConfigParams("task-123", "config-1"); - PushNotificationConfig config = new PushNotificationConfig("http://example.com", null, null, "config-1"); - TaskPushNotificationConfig result = new TaskPushNotificationConfig("task-123", config, null); - when(delegate.onGetTaskPushNotificationConfig(params, context)).thenReturn(result); - - TaskPushNotificationConfig actualResult = decorator.onGetTaskPushNotificationConfig(params, context); - - assertEquals(result, actualResult); - verify(tracer).spanBuilder(A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void onGetTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { - GetTaskPushNotificationConfigParams params = new GetTaskPushNotificationConfigParams("task-123", ""); - A2AError error = new TaskNotFoundError(); - when(delegate.onGetTaskPushNotificationConfig(params, context)).thenThrow(error); - - assertThrows(TaskNotFoundError.class, () -> decorator.onGetTaskPushNotificationConfig(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class ResubscribeToTaskTests { - @Test - void onResubscribeToTask_createsSpanWithSpecialMessage() throws A2AError { - TaskIdParams params = new TaskIdParams("task-123"); - Flow.Publisher publisher = mock(Flow.Publisher.class); - when(delegate.onSubscribeToTask(params, context)).thenReturn(publisher); - - Flow.Publisher actualResult = decorator.onSubscribeToTask(params, context); - - assertEquals(publisher, actualResult); - verify(tracer).spanBuilder(A2AMethods.SUBSCRIBE_TO_TASK_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, "Stream publisher created"); - verify(span).setStatus(StatusCode.OK); - } - - @Test - void onResubscribeToTask_withError_setsErrorStatus() throws A2AError { - TaskIdParams params = new TaskIdParams("task-123"); - A2AError error = new TaskNotFoundError(); - when(delegate.onSubscribeToTask(params, context)).thenThrow(error); - - assertThrows(TaskNotFoundError.class, () -> decorator.onSubscribeToTask(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class ListTaskPushNotificationConfigTests { - @Test - void onListTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-123"); - ListTaskPushNotificationConfigResult result = new ListTaskPushNotificationConfigResult(Collections.emptyList(), null); - when(delegate.onListTaskPushNotificationConfig(params, context)).thenReturn(result); - - ListTaskPushNotificationConfigResult actualResult = decorator.onListTaskPushNotificationConfig(params, context); - - assertEquals(result, actualResult); - verify(tracer).spanBuilder(A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - verify(span).end(); - } - - @Test - void onListTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-123"); - A2AError error = new InvalidRequestError("Invalid request"); - when(delegate.onListTaskPushNotificationConfig(params, context)).thenThrow(error); - - assertThrows(InvalidRequestError.class, () -> decorator.onListTaskPushNotificationConfig(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class DeleteTaskPushNotificationConfigTests { - @Test - void onDeleteTaskPushNotificationConfig_createsSpanAndDelegatesToHandler() throws A2AError { - DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams("task-123", "config-123"); - doNothing().when(delegate).onDeleteTaskPushNotificationConfig(params, context); - - decorator.onDeleteTaskPushNotificationConfig(params, context); - - verify(tracer).spanBuilder(A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setStatus(StatusCode.OK); - verify(span, never()).setAttribute(eq(GENAI_RESPONSE), anyString()); - verify(span).end(); - } - - @Test - void onDeleteTaskPushNotificationConfig_withError_setsErrorStatus() throws A2AError { - DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams("task-123", "config-123"); - A2AError error = new TaskNotFoundError(); - doThrow(error).when(delegate).onDeleteTaskPushNotificationConfig(params, context); - - assertThrows(TaskNotFoundError.class, () -> decorator.onDeleteTaskPushNotificationConfig(params, context)); - - verify(span).setAttribute(ERROR_TYPE, error.getMessage()); - verify(span).setStatus(StatusCode.ERROR, error.getMessage()); - verify(span).end(); - } - } - - @Nested - class SpanLifecycleTests { - @Test - void allMethods_createAndEndSpans() throws A2AError { - TaskQueryParams params = new TaskQueryParams("task-123", null); - Task result = Task.builder() - .id("task-123") - .contextId("ctx-1") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - when(delegate.onGetTask(params, context)).thenReturn(result); - - decorator.onGetTask(params, context); - - verify(span, times(1)).makeCurrent(); - verify(span, times(1)).end(); - } - - @Test - void spanAttributes_setCorrectly() throws A2AError { - TaskQueryParams params = new TaskQueryParams("task-123", null); - Task result = Task.builder() - .id("task-123") - .contextId("ctx-1") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .history(Collections.emptyList()) - .artifacts(Collections.emptyList()) - .build(); - when(delegate.onGetTask(params, context)).thenReturn(result); - - decorator.onGetTask(params, context); - - verify(tracer).spanBuilder(A2AMethods.GET_TASK_METHOD); - verify(spanBuilder).setSpanKind(SpanKind.SERVER); - verify(spanBuilder).setAttribute(GENAI_REQUEST, params.toString()); - verify(span).setAttribute(GENAI_RESPONSE, result.toString()); - verify(span).setStatus(StatusCode.OK); - } - } -} diff --git a/extras/push-notification-config-store-database-jpa/README.md b/extras/push-notification-config-store-database-jpa/README.md deleted file mode 100644 index 3e1d49143..000000000 --- a/extras/push-notification-config-store-database-jpa/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# A2A Java SDK - JPA Database PushNotificationConfigStore - -This module provides a JPA-based implementation of the `PushNotificationConfigStore` interface that persists push notification configurations to a relational database instead of keeping them in memory. - -The persistence is done with the Jakarta Persistence API, so this should be suitable for any JPA 3.0+ provider and Jakarta EE application server. - -## Quick Start - -### 1. Add Dependency - -Add this module to your project's `pom.xml`: - -```xml - - io.github.a2asdk - a2a-java-extras-push-notification-config-store-database-jpa - ${a2a.version} - -``` - -The `JpaDatabasePushNotificationConfigStore` is annotated in such a way that it should take precedence over the default `InMemoryPushNotificationConfigStore`. Hence, it is a drop-in replacement. - -### 2. Configure Database - -The following examples assume you are using PostgreSQL as your database. To use another database, adjust as needed for your environment. - -#### For Quarkus Reference Servers - -Add to your `application.properties`: - -```properties -# Database configuration -quarkus.datasource.db-kind=postgresql -quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/a2a_db -quarkus.datasource.username=your_username -quarkus.datasource.password=your_password - -# Hibernate configuration -quarkus.hibernate-orm.database.generation=update -``` - -#### For WildFly/Jakarta EE Servers - -Create or update your `persistence.xml`: - -```xml - - - - java:jboss/datasources/A2ADataSource - - io.a2a.extras.pushnotificationconfigstore.database.jpa.JpaPushNotificationConfig - true - - - - - - - - -``` - -### 3. Database Schema - -The module will automatically create the required table, which uses a composite primary key: - -```sql -CREATE TABLE a2a_push_notification_configs ( - task_id VARCHAR(255) NOT NULL, - config_id VARCHAR(255) NOT NULL, - task_data TEXT NOT NULL, - PRIMARY KEY (task_id, config_id) -); -``` - -## Configuration Options - -### Persistence Unit Name - -The module uses the persistence unit name `"a2a-java"`. Ensure your `persistence.xml` defines a persistence unit with this name. diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml deleted file mode 100644 index 41bae5d6b..000000000 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-extras-push-notification-config-store-database-jpa - - jar - - Java A2A Extras: JPA Database PushNotificationConfigStore - Java SDK for the Agent2Agent Protocol (A2A) - Extras - JPA Database PushNotificationConfigStore - - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - jakarta.annotation - jakarta.annotation-api - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - jakarta.persistence - jakarta.persistence-api - - - org.slf4j - slf4j-api - - - - io.quarkus - quarkus-junit5 - test - - - io.quarkus - quarkus-rest-client - test - - - org.junit.jupiter - junit-jupiter-api - test - - - org.mockito - mockito-core - test - - - io.rest-assured - rest-assured - test - - - jakarta.transaction - jakarta.transaction-api - - - io.quarkus - quarkus-hibernate-orm - test - - - io.quarkus - quarkus-jdbc-h2 - test - - - - ${project.groupId} - a2a-java-sdk-reference-jsonrpc - test - - - ${project.groupId} - a2a-java-sdk-client-transport-jsonrpc - test - - - ${project.groupId} - a2a-java-sdk-client - test - - - io.quarkus - quarkus-reactive-routes - test - - - diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java b/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java deleted file mode 100644 index 5049bc9a4..000000000 --- a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java +++ /dev/null @@ -1,168 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -import jakarta.persistence.TypedQuery; -import java.time.Instant; -import java.util.List; - -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Alternative; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.transaction.Transactional; - -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.util.PageToken; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.TaskPushNotificationConfig; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -@Alternative -@Priority(50) -public class JpaDatabasePushNotificationConfigStore implements PushNotificationConfigStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(JpaDatabasePushNotificationConfigStore.class); - - private static final Instant NULL_TIMESTAMP_SENTINEL = Instant.EPOCH; - - @PersistenceContext(unitName = "a2a-java") - EntityManager em; - - @Transactional - @Override - public PushNotificationConfig setInfo(String taskId, PushNotificationConfig notificationConfig) { - // Ensure config has an ID - default to taskId if not provided (mirroring InMemoryPushNotificationConfigStore behavior) - PushNotificationConfig.Builder builder = PushNotificationConfig.builder(notificationConfig); - if (notificationConfig.id() == null || notificationConfig.id().isEmpty()) { - // This means the taskId and configId are same. This will not allow having multiple configs for a single Task. - // The configId is a required field in the spec and should not be empty - builder.id(taskId); - } - notificationConfig = builder.build(); - - LOGGER.debug("Saving PushNotificationConfig for Task '{}' with ID: {}", taskId, notificationConfig.id()); - try { - TaskConfigId configId = new TaskConfigId(taskId, notificationConfig.id()); - - // Check if entity already exists - JpaPushNotificationConfig existingJpaConfig = em.find(JpaPushNotificationConfig.class, configId); - - if (existingJpaConfig != null) { - // Update existing entity - existingJpaConfig.setConfig(notificationConfig); - LOGGER.debug("Updated existing PushNotificationConfig for Task '{}' with ID: {}", - taskId, notificationConfig.id()); - } else { - // Create new entity - JpaPushNotificationConfig jpaConfig = JpaPushNotificationConfig.createFromConfig(taskId, notificationConfig); - em.persist(jpaConfig); - LOGGER.debug("Persisted new PushNotificationConfig for Task '{}' with ID: {}", - taskId, notificationConfig.id()); - } - } catch (JsonProcessingException e) { - LOGGER.error("Failed to serialize PushNotificationConfig for Task '{}' with ID: {}", - taskId, notificationConfig.id(), e); - throw new RuntimeException("Failed to serialize PushNotificationConfig for Task '" + - taskId + "' with ID: " + notificationConfig.id(), e); - } - return notificationConfig; - } - - @Transactional - @Override - public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConfigParams params) { - String taskId = params.id(); - LOGGER.debug("Retrieving PushNotificationConfigs for Task '{}' with params: pageSize={}, pageToken={}", - taskId, params.pageSize(), params.pageToken()); - - // Parse pageToken once at the beginning - PageToken pageToken = PageToken.fromString(params.pageToken()); - - try { - StringBuilder queryBuilder = new StringBuilder("SELECT c FROM JpaPushNotificationConfig c WHERE c.id.taskId = :taskId"); - - if (pageToken != null) { - // Keyset pagination: get tasks where timestamp < tokenTimestamp OR (timestamp = tokenTimestamp AND id > tokenId) - // All tasks have timestamps (TaskStatus canonical constructor ensures this) - queryBuilder.append(" AND (COALESCE(c.createdAt, :nullSentinel) < :tokenTimestamp OR (COALESCE(c.createdAt, :nullSentinel) = :tokenTimestamp AND c.id.configId > :tokenId))"); - } - - queryBuilder.append(" ORDER BY COALESCE(c.createdAt, :nullSentinel) DESC, c.id.configId ASC"); - - TypedQuery query = em.createQuery(queryBuilder.toString(), JpaPushNotificationConfig.class); - query.setParameter("taskId", taskId); - query.setParameter("nullSentinel", NULL_TIMESTAMP_SENTINEL); - - if (pageToken != null) { - query.setParameter("tokenTimestamp", pageToken.timestamp()); - query.setParameter("tokenId", pageToken.id()); - } - - int pageSize = params.getEffectivePageSize(); - query.setMaxResults(pageSize + 1); - List jpaConfigsPage = query.getResultList(); - - String nextPageToken = null; - if (jpaConfigsPage.size() > pageSize) { - // There are more results than the page size, and in this case, a nextToken should be created with the last item. - // Format: "timestamp_millis:taskId" for keyset pagination - jpaConfigsPage = jpaConfigsPage.subList(0, pageSize); - JpaPushNotificationConfig lastConfig = jpaConfigsPage.get(jpaConfigsPage.size() - 1); - Instant timestamp = lastConfig.getCreatedAt() != null ? lastConfig.getCreatedAt() : NULL_TIMESTAMP_SENTINEL; - nextPageToken = new PageToken(timestamp, lastConfig.getId().getConfigId()).toString(); - } - - List configs = jpaConfigsPage.stream() - .map(jpaConfig -> { - try { - return jpaConfig.getConfig(); - } catch (JsonProcessingException e) { - LOGGER.error("Failed to deserialize PushNotificationConfig for Task '{}' with ID: {}", - taskId, jpaConfig.getId().getConfigId(), e); - throw new RuntimeException("Failed to deserialize PushNotificationConfig for Task '" + - taskId + "' with ID: " + jpaConfig.getId().getConfigId(), e); - } - }) - .toList(); - - LOGGER.debug("Successfully retrieved {} PushNotificationConfigs for Task '{}'", configs.size(), taskId); - - List taskPushNotificationConfigs = configs.stream() - .map(config -> new TaskPushNotificationConfig(params.id(), config, params.tenant())) - .collect(Collectors.toList()); - - return new ListTaskPushNotificationConfigResult(taskPushNotificationConfigs, nextPageToken); - } catch (Exception e) { - LOGGER.error("Failed to retrieve PushNotificationConfigs for Task '{}'", taskId, e); - throw e; - } - } - - @Transactional - @Override - public void deleteInfo(String taskId, String configId) { - if (configId == null) { - configId = taskId; - } - - LOGGER.debug("Deleting PushNotificationConfig for Task '{}' with Config ID: {}", taskId, configId); - JpaPushNotificationConfig jpaConfig = em.find(JpaPushNotificationConfig.class, - new TaskConfigId(taskId, configId)); - - if (jpaConfig != null) { - em.remove(jpaConfig); - LOGGER.debug("Successfully deleted PushNotificationConfig for Task '{}' with Config ID: {}", - taskId, configId); - } else { - LOGGER.debug("PushNotificationConfig not found for deletion with Task '{}' and Config ID: {}", - taskId, configId); - } - } - -} diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java b/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java deleted file mode 100644 index d38b136ca..000000000 --- a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -import jakarta.persistence.Column; -import jakarta.persistence.EmbeddedId; -import jakarta.persistence.Entity; -import jakarta.persistence.PrePersist; -import jakarta.persistence.Table; -import jakarta.persistence.Transient; - -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.PushNotificationConfig; -import java.time.Instant; - -@Entity -@Table(name = "a2a_push_notification_configs") -public class JpaPushNotificationConfig { - @EmbeddedId - private TaskConfigId id; - - @Column(name = "task_data", columnDefinition = "TEXT", nullable = false) - private String configJson; - - @Column(name = "created_at") - private Instant createdAt; - - @Transient - private PushNotificationConfig config; - - // Default constructor required by JPA - public JpaPushNotificationConfig() { - } - - public JpaPushNotificationConfig(TaskConfigId id, String configJson) { - this.id = id; - this.configJson = configJson; - } - - @PrePersist - protected void onCreate() { - if (createdAt == null) { - createdAt = Instant.now(); - } - } - - public TaskConfigId getId() { - return id; - } - - public void setId(TaskConfigId id) { - this.id = id; - } - - public void setConfigJson(String configJson) { - this.configJson = configJson; - } - - public PushNotificationConfig getConfig() throws JsonProcessingException { - if (config == null) { - this.config = JsonUtil.fromJson(configJson, PushNotificationConfig.class); - } - return config; - } - - public void setConfig(PushNotificationConfig config) throws JsonProcessingException { - if (config.id() == null || !config.id().equals(id.getConfigId())) { - throw new IllegalArgumentException("Mismatched config id. " + - "Expected '" + id.getConfigId() + "'. Got: '" + config.id() + "'"); - } - configJson = JsonUtil.toJson(config); - this.config = config; - } - - public Instant getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Instant createdAt) { - this.createdAt = createdAt; - } - - static JpaPushNotificationConfig createFromConfig(String taskId, PushNotificationConfig config) throws JsonProcessingException { - String json = JsonUtil.toJson(config); - JpaPushNotificationConfig jpaPushNotificationConfig = - new JpaPushNotificationConfig(new TaskConfigId(taskId, config.id()), json); - jpaPushNotificationConfig.config = config; - return jpaPushNotificationConfig; - } -} diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java b/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java deleted file mode 100644 index 9b66a8ea4..000000000 --- a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/TaskConfigId.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -import java.io.Serializable; -import java.util.Objects; - -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; - -@Embeddable -public class TaskConfigId implements Serializable { - - @Column(name = "task_id") - private String taskId; - - @Column(name = "config_id") - private String configId; - - // No-argument constructor (required by JPA) - public TaskConfigId() { - } - - public TaskConfigId(String taskId, String configId) { - this.taskId = taskId; - this.configId = configId; - } - - // Getters and setters... - - public String getTaskId() { - return taskId; - } - - public void setTaskId(String taskId) { - this.taskId = taskId; - } - - public String getConfigId() { - return configId; - } - - public void setConfigId(String configId) { - this.configId = configId; - } - - // hashCode() and equals() implementations - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TaskConfigId that = (TaskConfigId) o; - return Objects.equals(taskId, that.taskId) && - Objects.equals(configId, that.configId); - } - - @Override - public int hashCode() { - return Objects.hash(taskId, configId); - } -} diff --git a/extras/push-notification-config-store-database-jpa/src/main/resources/META-INF/beans.xml b/extras/push-notification-config-store-database-jpa/src/main/resources/META-INF/beans.xml deleted file mode 100644 index ffc8abb42..000000000 --- a/extras/push-notification-config-store-database-jpa/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java deleted file mode 100644 index 75a0df5de..000000000 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java +++ /dev/null @@ -1,572 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import java.util.Queue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; - -import io.a2a.client.Client; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.Message; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TextPart; -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * End-to-end integration test that verifies the JPA PushNotificationConfigStore works correctly - * with the full client-server flow using the Client API. - */ -@QuarkusTest -public class JpaDatabasePushNotificationConfigStoreIntegrationTest { - - @Inject - PushNotificationConfigStore pushNotificationConfigStore; - - @Inject - @PublicAgentCard - AgentCard agentCard; - - @Inject - MockPushNotificationSender mockPushNotificationSender; - - private Client client; - - @BeforeEach - public void setup() throws A2AClientException { - // Clear any previous notifications - mockPushNotificationSender.clear(); - - // Create client configuration - enable streaming for automatic push notifications - ClientConfig clientConfig = new ClientConfig.Builder() - .setStreaming(true) - .build(); - - // Build client with JSON-RPC transport - client = Client.builder(agentCard) - .clientConfig(clientConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - } - - @Test - public void testIsJpaDatabasePushNotificationConfigStore() { - assertInstanceOf(JpaDatabasePushNotificationConfigStore.class, pushNotificationConfigStore); - } - - @Test - public void testDirectNotificationTrigger() { - // Simple test to verify the mock notification mechanism works - mockPushNotificationSender.clear(); - - Task testTask = Task.builder() - .id("direct-test-task") - .contextId("test-context") - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_SUBMITTED)) - .build(); - - // Directly trigger the mock - mockPushNotificationSender.sendNotification(testTask); - - // Verify it was captured - Queue captured = mockPushNotificationSender.getCapturedTasks(); - assertEquals(1, captured.size()); - assertEquals("direct-test-task", captured.peek().id()); - } - - @Test - public void testJpaDatabasePushNotificationConfigStoreIntegration() throws Exception { - final String taskId = "push-notify-test-" + System.currentTimeMillis(); - final String contextId = "test-context"; - - // Step 1: Create the task - Message createMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("create"))) // Send the "create" command - .taskId(taskId) - .messageId("test-msg-1") - .contextId(contextId) - .build(); - - // Use a latch to wait for the first operation to complete - CountDownLatch createLatch = new CountDownLatch(1); - client.sendMessage(createMessage, List.of((event, card) -> createLatch.countDown()), (e) -> createLatch.countDown()); - assertTrue(createLatch.await(10, TimeUnit.SECONDS), "Timeout waiting for task creation"); - - // Step 2: Set the push notification configuration - PushNotificationConfig pushConfig = PushNotificationConfig.builder() - .url("http://localhost:9999/mock-endpoint") - .token("test-token-123") - .id("test-config-1") - .build(); - - TaskPushNotificationConfig taskPushConfig = new TaskPushNotificationConfig(taskId, pushConfig, ""); - TaskPushNotificationConfig setResult = client.createTaskPushNotificationConfiguration(taskPushConfig); - assertNotNull(setResult); - - // Step 3: Verify the configuration was stored using client API - TaskPushNotificationConfig storedConfig = client.getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams(taskId, "test-config-1")); - - assertNotNull(storedConfig); - assertEquals(taskId, storedConfig.taskId()); - assertEquals("test-config-1", storedConfig.config().id()); - assertEquals("http://localhost:9999/mock-endpoint", storedConfig.config().url()); - assertEquals("test-token-123", storedConfig.config().token()); - - // Step 4: Update the task to trigger the notification - Message updateMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("update"))) // Send the "update" command - .taskId(taskId) - .messageId("test-msg-2") - .contextId(contextId) - .build(); - - CountDownLatch updateLatch = new CountDownLatch(1); - client.sendMessage(updateMessage, List.of((event, card) -> updateLatch.countDown()), (e) -> updateLatch.countDown()); - assertTrue(updateLatch.await(10, TimeUnit.SECONDS), "Timeout waiting for task update"); - - // Step 5: Poll for the async notification to be captured - // With the new StreamingEventKind support, we receive all event types (Task, Message, TaskArtifactUpdateEvent, etc.) - long end = System.currentTimeMillis() + 5000; - boolean notificationReceived = false; - - while (System.currentTimeMillis() < end) { - if (!mockPushNotificationSender.getCapturedEvents().isEmpty()) { - notificationReceived = true; - break; - } - Thread.sleep(100); - } - - assertTrue(notificationReceived, "Timeout waiting for push notification."); - - // Step 6: Verify the captured notification - // Check if we received events for this task (could be Task, TaskArtifactUpdateEvent, etc.) - Queue capturedEvents = mockPushNotificationSender.getCapturedEvents(); - - // Look for Task events with artifacts OR TaskArtifactUpdateEvent for this task - boolean hasTaskWithArtifact = capturedEvents.stream() - .filter(e -> e instanceof Task) - .map(e -> (Task) e) - .anyMatch(t -> taskId.equals(t.id()) && t.artifacts() != null && t.artifacts().size() > 0); - - boolean hasArtifactUpdateEvent = capturedEvents.stream() - .filter(e -> e instanceof io.a2a.spec.TaskArtifactUpdateEvent) - .map(e -> (io.a2a.spec.TaskArtifactUpdateEvent) e) - .anyMatch(e -> taskId.equals(e.taskId())); - - assertTrue(hasTaskWithArtifact || hasArtifactUpdateEvent, - "Notification should contain either Task with artifacts or TaskArtifactUpdateEvent for task " + taskId); - - // Step 7: Clean up - delete the push notification configuration - client.deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams(taskId, "test-config-1")); - - // Verify deletion by asserting that getting the config now throws an exception - assertThrows(A2AClientException.class, () -> { - client.getTaskPushNotificationConfiguration(new GetTaskPushNotificationConfigParams(taskId, "test-config-1")); - }, "Getting a deleted config should throw an A2AClientException"); - } - - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() - .url(url) - .id(configId) - .token(token) - .build(); - } - - @Test - @Transactional - public void testPaginationWithPageSize() { - String taskId = "task_pagination_" + System.currentTimeMillis(); - // Create 5 configs - createSamples(taskId, 5); - // Request first page with pageSize=2 - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result); - assertEquals(2, result.configs().size(), "Should return 2 configs"); - assertNotNull(result.nextPageToken(), "Should have nextPageToken when more items exist"); - } - - @Test - @Transactional - public void testPaginationWithPageToken() { - String taskId = "task_pagination_token_" + System.currentTimeMillis(); - // Create 5 configs - createSamples(taskId, 5); - - // Get first page - ListTaskPushNotificationConfigParams firstPageParams = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult firstPage = pushNotificationConfigStore.getInfo(firstPageParams); - assertNotNull(firstPage.nextPageToken()); - - // Get second page using nextPageToken - ListTaskPushNotificationConfigParams secondPageParams = new ListTaskPushNotificationConfigParams( - taskId, 2, firstPage.nextPageToken(), ""); - ListTaskPushNotificationConfigResult secondPage = pushNotificationConfigStore.getInfo(secondPageParams); - - assertNotNull(secondPage); - assertEquals(2, secondPage.configs().size(), "Should return 2 configs for second page"); - assertNotNull(secondPage.nextPageToken(), "Should have nextPageToken when more items exist"); - - // Verify NO overlap between pages - collect all IDs from both pages - List firstPageIds = firstPage.configs().stream() - .map(c -> c.config().id()) - .toList(); - List secondPageIds = secondPage.configs().stream() - .map(c -> c.config().id()) - .toList(); - - // Check that no ID from first page appears in second page - for (String id : firstPageIds) { - assertTrue(!secondPageIds.contains(id), - "Config " + id + " appears in both pages - overlap detected!"); - } - - // Also verify the pages are sequential (first page ends before second page starts) - // Since configs are created in order, we can verify the IDs. - // There is no spec about pagination for PushNotifications, hence following the Task List - // behavior by which recent notifications are returned first - assertEquals("cfg4", firstPageIds.get(0)); - assertEquals("cfg3", firstPageIds.get(1)); - assertEquals("cfg2", secondPageIds.get(0)); - assertEquals("cfg1", secondPageIds.get(1)); - } - - @Test - @Transactional - public void testPaginationLastPage() { - String taskId = "task_pagination_last_" + System.currentTimeMillis(); - // Create 5 configs - createSamples(taskId, 5); - - // Get first page (2 items) - ListTaskPushNotificationConfigParams firstPageParams = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult firstPage = pushNotificationConfigStore.getInfo(firstPageParams); - - // Get second page (2 items) - ListTaskPushNotificationConfigParams secondPageParams = new ListTaskPushNotificationConfigParams( - taskId, 2, firstPage.nextPageToken(), ""); - ListTaskPushNotificationConfigResult secondPage = pushNotificationConfigStore.getInfo(secondPageParams); - - // Get last page (1 item remaining) - ListTaskPushNotificationConfigParams lastPageParams = new ListTaskPushNotificationConfigParams( - taskId, 2, secondPage.nextPageToken(), ""); - ListTaskPushNotificationConfigResult lastPage = pushNotificationConfigStore.getInfo(lastPageParams); - - assertNotNull(lastPage); - assertEquals(1, lastPage.configs().size(), "Last page should have 1 remaining config"); - assertNull(lastPage.nextPageToken(), "Last page should not have nextPageToken"); - } - - @Test - @Transactional - public void testPaginationWithZeroPageSize() { - String taskId = "task_pagination_zero_" + System.currentTimeMillis(); - // Create 5 configs - createSamples(taskId, 5); - - // Request with pageSize=0 should return all configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 0, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result); - assertEquals(5, result.configs().size(), "Should return all 5 configs when pageSize=0"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when returning all"); - } - - @Test - @Transactional - public void testPaginationWithNegativePageSize() { - String taskId = "task_pagination_negative_" + System.currentTimeMillis(); - // Create 3 configs - createSamples(taskId, 3); - - // Request with negative pageSize should return all configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, -1, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result); - assertEquals(3, result.configs().size(), "Should return all configs when pageSize is negative"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when returning all"); - } - - @Test - @Transactional - public void testPaginationPageSizeLargerThanConfigs() { - String taskId = "task_pagination_large_" + System.currentTimeMillis(); - // Create 3 configs - createSamples(taskId, 3); - - // Request with pageSize larger than available configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 10, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result); - assertEquals(3, result.configs().size(), "Should return all 3 configs"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when all configs fit in one page"); - } - - @Test - @Transactional - public void testPaginationExactlyPageSize() { - String taskId = "task_pagination_exact_" + System.currentTimeMillis(); - // Create exactly 3 configs - createSamples(taskId, 3); - - // Request with pageSize equal to number of configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 3, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result); - assertEquals(3, result.configs().size(), "Should return all 3 configs"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when configs exactly match pageSize"); - } - - @Test - @Transactional - public void testPaginationWithInvalidToken() { - String taskId = "task_pagination_invalid_token_" + System.currentTimeMillis(); - // Create 5 configs - createSamples(taskId, 5); - - // Request with invalid pageToken - should throw InvalidParamsError for invalid format - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams( - taskId, 2, "invalid_token_that_does_not_exist", ""); - - assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), - "Should throw InvalidParamsError for invalid pageToken format (missing colon)"); - } - - @Test - @Transactional - public void testPaginationEmptyTaskWithPageSize() { - String taskId = "task_pagination_empty_" + System.currentTimeMillis(); - // No configs created - - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result); - assertTrue(result.configs().isEmpty(), "Should return empty list for non-existent task"); - assertNull(result.nextPageToken(), "Should not have nextPageToken for empty result"); - } - - @Test - @Transactional - public void testPaginationFullIteration() { - String taskId = "task_pagination_full_" + System.currentTimeMillis(); - // Create 7 configs - createSamples(taskId, 7); - - // Iterate through all pages with pageSize=3 - int totalCollected = 0; - String pageToken = ""; - int pageCount = 0; - - do { - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 3, pageToken, ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - totalCollected += result.configs().size(); - pageToken = result.nextPageToken(); - pageCount++; - - // Safety check to prevent infinite loop - assertTrue(pageCount <= 7, "Should not have more than 7 pages for 7 configs"); - - } while (pageToken != null); - - assertEquals(7, totalCollected, "Should collect all 7 configs across all pages"); - assertEquals(3, pageCount, "Should have exactly 3 pages (3+3+1)"); - } - - @Test - @Transactional - public void testPageTokenWithNonNumericTimestamp() { - String taskId = "task_malformed_token_" + System.currentTimeMillis(); - createSamples(taskId, 3); - - ListTaskPushNotificationConfigParams params = - new ListTaskPushNotificationConfigParams(taskId, 2, "not_a_number:cfg1", ""); - - assertThrows(io.a2a.spec.InvalidParamsError.class, - () -> pushNotificationConfigStore.getInfo(params), - "Should throw InvalidParamsError for non-numeric timestamp in pageToken"); - } - - @Test - @Transactional - public void testPageTokenWithMissingColon() { - String taskId = "task_missing_colon_" + System.currentTimeMillis(); - createSamples(taskId, 5); - - ListTaskPushNotificationConfigParams params = - new ListTaskPushNotificationConfigParams(taskId, 2, "123456789cfg1", ""); - - assertThrows(io.a2a.spec.InvalidParamsError.class, () -> pushNotificationConfigStore.getInfo(params), - "Should throw InvalidParamsError for invalid pageToken format (missing colon)"); - } - - @Test - @Transactional - public void testPaginationBoundaryExactlyMaxResultsPlusOne() { - String taskId = "task_boundary_" + System.currentTimeMillis(); - - createSamples(taskId, 4); - - ListTaskPushNotificationConfigParams params = - new ListTaskPushNotificationConfigParams(taskId, 4, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertEquals(4, result.configs().size(), - "Should return all 4 configs when pageSize equals total count"); - assertNull(result.nextPageToken(), - "Should not have nextPageToken when count equals pageSize"); - } - - @Test - @Transactional - public void testMultipleTasksDoNotInterfere() { - String taskId1 = "task1_" + System.currentTimeMillis(); - String taskId2 = "task2_" + System.currentTimeMillis(); - - createSamples(taskId1, 3); - createSamples(taskId2, 2); - - ListTaskPushNotificationConfigResult result1 = - pushNotificationConfigStore.getInfo(new ListTaskPushNotificationConfigParams(taskId1)); - ListTaskPushNotificationConfigResult result2 = - pushNotificationConfigStore.getInfo(new ListTaskPushNotificationConfigParams(taskId2)); - - assertEquals(3, result1.configs().size(), "Task1 should have 3 configs"); - assertEquals(2, result2.configs().size(), "Task2 should have 2 configs"); - - List task1Ids = result1.configs().stream() - .map(c -> taskId1 + c.config().id()) - .toList(); - List task2Ids = result2.configs().stream() - .map(c -> taskId2 + c.config().id()) - .toList(); - - for (String id : task1Ids) { - assertTrue(!task2Ids.contains(id), - "Configs from different tasks should not overlap"); - } - } - - @Test - @Transactional - public void testGetInfoWithNonExistentTaskIdDoesNotThrow() { - String nonExistentTaskId = "non_existent_task_" + System.currentTimeMillis(); - - ListTaskPushNotificationConfigParams params = - new ListTaskPushNotificationConfigParams(nonExistentTaskId, 10, "", ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result, "Result should not be null"); - assertTrue(result.configs().isEmpty(), - "Should return empty list for non-existent task"); - assertNull(result.nextPageToken(), - "Should not have nextPageToken for empty result"); - } - - @Test - @Transactional - public void testGetInfoReturnsTenantFromParams() { - String taskId = "task_tenant_" + System.currentTimeMillis(); - String tenant = "test-tenant-123"; - - PushNotificationConfig config = createSamplePushConfig( - "http://url.com/callback", "cfg1", "token"); - pushNotificationConfigStore.setInfo(taskId, config); - - ListTaskPushNotificationConfigParams params = - new ListTaskPushNotificationConfigParams(taskId, 0, "", tenant); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - assertNotNull(result); - assertEquals(1, result.configs().size()); - assertEquals(tenant, result.configs().get(0).tenant(), - "Tenant from params should be returned in result"); - } - - @Test - @Transactional - public void testPaginationOrderingConsistency() { - String taskId = "task_ordering_consistency_" + System.currentTimeMillis(); - createSamples(taskId, 15); - - List allConfigIds = new java.util.ArrayList<>(); - String pageToken = ""; - int pageCount = 0; - - do { - ListTaskPushNotificationConfigParams params = - new ListTaskPushNotificationConfigParams(taskId, 3, pageToken, ""); - ListTaskPushNotificationConfigResult result = pushNotificationConfigStore.getInfo(params); - - result.configs().forEach(c -> - allConfigIds.add(c.config().id())); - pageToken = result.nextPageToken(); - pageCount++; - - assertTrue(pageCount <= 20, "Should not have more than 20 pages for 15 configs"); - - } while (pageToken != null); - - assertEquals(15, allConfigIds.size(), "Should retrieve all 15 configs"); - assertEquals(15, new java.util.HashSet<>(allConfigIds).size(), - "All config IDs should be unique - no duplicates"); - - assertEquals("cfg14", allConfigIds.get(0), - "First config should be most recently created (DESC order)"); - assertEquals("cfg0", allConfigIds.get(14), - "Last config should be oldest created"); - } - private void createSamples(String taskId, int size) { - // Create configs with slight delays to ensure unique timestamps for deterministic ordering - for (int i = 0; i < size; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - pushNotificationConfigStore.setInfo(taskId, config); - - // Sleep briefly to ensure each config gets a unique timestamp - // This prevents non-deterministic ordering in pagination tests - try { - Thread.sleep(2); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Interrupted while creating test samples", e); - } - } - } -} diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java deleted file mode 100644 index ac5e6ffdf..000000000 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentCardProducer.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -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.AgentInterface; -import io.a2a.spec.TransportProtocol; -import io.quarkus.arc.profile.IfBuildProfile; - -/** - * Simple test AgentCard producer for our integration test. - * It declares that the agent supports push notifications. - */ -@ApplicationScoped -@IfBuildProfile("test") -public class JpaDatabasePushNotificationConfigStoreTestAgentCardProducer { - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return AgentCard.builder() - .name("JPA PushNotificationConfigStore Integration Test Agent") - .description("Test agent for verifying JPA PushNotificationConfigStore integration") - .version("1.0.0") - .supportedInterfaces( - Collections.singletonList( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:8081"))) // Port is managed by QuarkusTest - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .capabilities(AgentCapabilities.builder() - .pushNotifications(true) // Enable push notifications - .streaming(true) // Enable streaming for automatic push notifications - .build()) - .skills(List.of()) - .build(); - } -} diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java deleted file mode 100644 index 4061a3619..000000000 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -import java.util.List; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; - -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.A2AError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import io.quarkus.arc.profile.IfBuildProfile; - -/** - * Simple test AgentExecutor that updates the task, which in turn - * will trigger the PushNotificationSender. - */ -@IfBuildProfile("test") -@ApplicationScoped -public class JpaDatabasePushNotificationConfigStoreTestAgentExecutor { - - @Inject - PushNotificationSender pushNotificationSender; - - @Produces - public AgentExecutor agentExecutor() { - return new AgentExecutor() { - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - String command = getLastTextPart(context.getMessage()); - - // Switch based on the command from the test client - switch (command) { - case "create": - agentEmitter.submit(); - break; - case "update": - // Perform a meaningful update, like adding an artifact. - // This state change is what will trigger the notification. - agentEmitter.addArtifact(List.of(new TextPart("updated-artifact")), "art-1", "test", null); - break; - default: - // On the first message (which might have no text), just submit. - agentEmitter.submit(); - break; - } - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - agentEmitter.cancel(); - } - }; - } - - private String getLastTextPart(Message message) throws A2AError { - if (message.parts() == null || message.parts().isEmpty()) { - return ""; - } - Part part = message.parts().get(message.parts().size() - 1); - if (part instanceof TextPart) { - return ((TextPart) part).text(); - } - throw new InvalidRequestError("Last part is not text"); - } -} diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java deleted file mode 100644 index 6023a74b9..000000000 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java +++ /dev/null @@ -1,374 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.List; - -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.server.tasks.BasePushNotificationSender; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@QuarkusTest -public class JpaPushNotificationConfigStoreTest { - - @Inject - PushNotificationConfigStore configStore; - - private BasePushNotificationSender notificationSender; - - @Mock - private A2AHttpClient mockHttpClient; - - @Mock - private A2AHttpClient.PostBuilder mockPostBuilder; - - @Mock - private A2AHttpResponse mockHttpResponse; - - @BeforeEach - public void setUp() { - MockitoAnnotations.openMocks(this); - notificationSender = new BasePushNotificationSender(configStore, mockHttpClient); - } - - @Test - public void testIsJpaDatabasePushNotificationConfigStore() { - assertInstanceOf(JpaDatabasePushNotificationConfigStore.class, configStore); - } - - private Task createSampleTask(String taskId, TaskState state) { - return Task.builder() - .id(taskId) - .contextId("ctx456") - .status(new TaskStatus(state)) - .build(); - } - - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() - .url(url) - .id(configId) - .token(token) - .build(); - } - - @Test - @Transactional - public void testSetInfoAddsNewConfig() { - String taskId = "task_new"; - PushNotificationConfig config = createSamplePushConfig("http://new.url/callback", "cfg1", null); - - PushNotificationConfig result = configStore.setInfo(taskId, config); - - assertNotNull(result); - assertEquals(config.url(), result.url()); - assertEquals(config.id(), result.id()); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); - } - - @Test - @Transactional - public void testSetInfoAppendsToExistingConfig() { - String taskId = "task_update"; - PushNotificationConfig initialConfig = createSamplePushConfig( - "http://initial.url/callback", "cfg_initial", null); - configStore.setInfo(taskId, initialConfig); - - PushNotificationConfig updatedConfig = createSamplePushConfig( - "http://updated.url/callback", "cfg_updated", null); - configStore.setInfo(taskId, updatedConfig); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(2, configResult.configs().size()); - - // Find the configs by ID since order might vary - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); - PushNotificationConfig foundInitial = configs.stream() - .filter(c -> "cfg_initial".equals(c.id())) - .findFirst() - .orElse(null); - PushNotificationConfig foundUpdated = configs.stream() - .filter(c -> "cfg_updated".equals(c.id())) - .findFirst() - .orElse(null); - - assertNotNull(foundInitial); - assertNotNull(foundUpdated); - assertEquals(initialConfig.url(), foundInitial.url()); - assertEquals(updatedConfig.url(), foundUpdated.url()); - } - - @Test - @Transactional - public void testSetInfoWithoutConfigId() { - String taskId = "task1"; - PushNotificationConfig initialConfig = PushNotificationConfig.builder() - .url("http://initial.url/callback") - .build(); // No ID set - - PushNotificationConfig result = configStore.setInfo(taskId, initialConfig); - assertEquals(taskId, result.id(), "Config ID should default to taskId when not provided"); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertEquals(1, configResult.configs().size()); - assertEquals(taskId, configResult.configs().get(0).config().id()); - - PushNotificationConfig updatedConfig = PushNotificationConfig.builder() - .url("http://initial.url/callback_new") - .build(); // No ID set - - PushNotificationConfig updatedResult = configStore.setInfo(taskId, updatedConfig); - assertEquals(taskId, updatedResult.id()); - - configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertEquals(1, configResult.configs().size(), "Should replace existing config with same ID rather than adding new one"); - assertEquals(updatedConfig.url(), configResult.configs().get(0).config().url()); - } - - @Test - @Transactional - public void testGetInfoExistingConfig() { - String taskId = "task_get_exist"; - PushNotificationConfig config = createSamplePushConfig("http://get.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); - } - - @Test - @Transactional - public void testGetInfoNonExistentConfig() { - String taskId = "task_get_non_exist"; - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertTrue(configResult.configs().isEmpty(), "Should return empty list for non-existent task ID"); - } - - @Test - @Transactional - public void testDeleteInfoExistingConfig() { - String taskId = "task_delete_exist"; - PushNotificationConfig config = createSamplePushConfig("http://delete.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - - configStore.deleteInfo(taskId, config.id()); - - ListTaskPushNotificationConfigResult configsAfterDelete = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configsAfterDelete); - assertTrue(configsAfterDelete.configs().isEmpty(), "Should return empty list when no configs remain after deletion"); - } - - @Test - @Transactional - public void testDeleteInfoNonExistentConfig() { - String taskId = "task_delete_non_exist"; - // Should not throw an error - configStore.deleteInfo(taskId, "non_existent_id"); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertTrue(configResult.configs().isEmpty(), "Should return empty list for non-existent task ID"); - } - - @Test - @Transactional - public void testDeleteInfoWithNullConfigId() { - String taskId = "task_delete_null_config"; - PushNotificationConfig config = PushNotificationConfig.builder() - .url("http://delete.this/callback") - .build(); // No ID set, will use taskId - configStore.setInfo(taskId, config); - - // Delete with null configId should use taskId - configStore.deleteInfo(taskId, null); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertTrue(configResult.configs().isEmpty(), "Should return empty list after deletion when using taskId as configId"); - } - - @Test - @Transactional - public void testSendNotificationSuccess() throws Exception { - String taskId = "task_send_success"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - configStore.setInfo(taskId, config); - - // Mock successful HTTP response - when(mockHttpClient.createPost()).thenReturn(mockPostBuilder); - when(mockPostBuilder.url(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.addHeader(CONTENT_TYPE, APPLICATION_JSON)).thenReturn(mockPostBuilder); - when(mockPostBuilder.body(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.post()).thenReturn(mockHttpResponse); - when(mockHttpResponse.success()).thenReturn(true); - - notificationSender.sendNotification(task); - - // Verify HTTP client was called - ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); - verify(mockHttpClient).createPost(); - verify(mockPostBuilder).url(config.url()); - verify(mockPostBuilder).addHeader(CONTENT_TYPE, APPLICATION_JSON); - verify(mockPostBuilder).body(bodyCaptor.capture()); - verify(mockPostBuilder).post(); - - // Verify the request body contains the task data - String sentBody = bodyCaptor.getValue(); - assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().name())); - } - - @Test - @Transactional - @Disabled("Token authentication is not yet implemented in BasePushNotificationSender (TODO auth)") - public void testSendNotificationWithToken() throws Exception { - String taskId = "task_send_with_token"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); - configStore.setInfo(taskId, config); - - // Mock successful HTTP response - when(mockHttpClient.createPost()).thenReturn(mockPostBuilder); - when(mockPostBuilder.url(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.body(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.post()).thenReturn(mockHttpResponse); - when(mockHttpResponse.success()).thenReturn(true); - - notificationSender.sendNotification(task); - - // TODO: Once token authentication is implemented, verify that: - // 1. The token is included in request headers (e.g., X-A2A-Notification-Token) - // 2. The HTTP client is called with proper authentication - // 3. The token from the config is actually used - - // For now, just verify basic HTTP client interaction - ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); - verify(mockHttpClient).createPost(); - verify(mockPostBuilder).url(config.url()); - verify(mockPostBuilder).body(bodyCaptor.capture()); - verify(mockPostBuilder).post(); - - // Verify the request body contains the task data - String sentBody = bodyCaptor.getValue(); - assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().name())); - } - - @Test - @Transactional - public void testSendNotificationNoConfig() throws Exception { - String taskId = "task_send_no_config"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - - notificationSender.sendNotification(task); - - // Verify HTTP client was never called - verify(mockHttpClient, never()).createPost(); - } - - @Test - @Transactional - public void testMultipleConfigsForSameTask() { - String taskId = "task_multiple"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); - - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(2, configResult.configs().size()); - - // Verify both configs are present - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); - assertTrue(configs.stream().anyMatch(c -> "cfg1".equals(c.id()))); - assertTrue(configs.stream().anyMatch(c -> "cfg2".equals(c.id()))); - } - - @Test - @Transactional - public void testDeleteSpecificConfigFromMultiple() { - String taskId = "task_delete_specific"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); - - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); - - // Delete only config1 - configStore.deleteInfo(taskId, "cfg1"); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - assertEquals("cfg2", configResult.configs().get(0).config().id()); - } - - @Test - @Transactional - public void testConfigStoreIntegration() { - String taskId = "integration_test"; - PushNotificationConfig config = createSamplePushConfig("http://example.com", "test_id", "test_token"); - - // Test that we can store and retrieve configurations - PushNotificationConfig storedConfig = configStore.setInfo(taskId, config); - assertEquals(config.url(), storedConfig.url()); - assertEquals(config.token(), storedConfig.token()); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - - // Test deletion - configStore.deleteInfo(taskId, storedConfig.id()); - ListTaskPushNotificationConfigResult afterDeletion = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertTrue(afterDeletion.configs().isEmpty()); - } -} diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java deleted file mode 100644 index 2275388a9..000000000 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/MockPushNotificationSender.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.a2a.extras.pushnotificationconfigstore.database.jpa; - -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Alternative; - -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; - -/** - * Mock implementation of PushNotificationSender for integration testing. - * Captures notifications in a thread-safe queue for test verification. - */ -@ApplicationScoped -@Alternative -@Priority(100) -public class MockPushNotificationSender implements PushNotificationSender { - - private final Queue capturedEvents = new ConcurrentLinkedQueue<>(); - - @Override - public void sendNotification(StreamingEventKind event) { - capturedEvents.add(event); - } - - public Queue getCapturedEvents() { - return capturedEvents; - } - - /** - * For backward compatibility - provides access to Task events only. - */ - public Queue getCapturedTasks() { - Queue tasks = new ConcurrentLinkedQueue<>(); - capturedEvents.stream() - .filter(e -> e instanceof Task) - .map(e -> (Task) e) - .forEach(tasks::add); - return tasks; - } - - public void clear() { - capturedEvents.clear(); - } -} diff --git a/extras/push-notification-config-store-database-jpa/src/test/resources/META-INF/persistence.xml b/extras/push-notification-config-store-database-jpa/src/test/resources/META-INF/persistence.xml deleted file mode 100644 index 4ae3b38d0..000000000 --- a/extras/push-notification-config-store-database-jpa/src/test/resources/META-INF/persistence.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - A2A Java SDK JPA TaskStore Test Configuration - - - io.a2a.extras.pushnotificationconfigstore.database.jpa.JpaPushNotificationConfig - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/extras/push-notification-config-store-database-jpa/src/test/resources/application.properties b/extras/push-notification-config-store-database-jpa/src/test/resources/application.properties deleted file mode 100644 index d9300cd2b..000000000 --- a/extras/push-notification-config-store-database-jpa/src/test/resources/application.properties +++ /dev/null @@ -1,14 +0,0 @@ -# Test configuration for JPA TaskStore -# H2 in-memory database for testing -quarkus.datasource.db-kind=h2 -quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -quarkus.datasource.username=sa -quarkus.datasource.password= - -# Hibernate configuration -quarkus.hibernate-orm.database.generation=drop-and-create -quarkus.hibernate-orm.log.sql=true -quarkus.hibernate-orm.log.format-sql=true - -# Transaction timeout (set to 30 minutes for debugging - 1800 seconds) -# quarkus.transaction-manager.default-transaction-timeout=1800s diff --git a/extras/queue-manager-replicated/README.md b/extras/queue-manager-replicated/README.md deleted file mode 100644 index 8756be0a2..000000000 --- a/extras/queue-manager-replicated/README.md +++ /dev/null @@ -1,411 +0,0 @@ -# A2A Java SDK - Replicated Queue Manager - -This module provides a replicated implementation of the `QueueManager` interface that enables event replication across multiple A2A instances using message brokers like Apache Kafka. It ensures that events generated in one A2A instance are propagated to other instances for distributed operation. - -The replication works by intercepting events as they are enqueued and sending them to a message broker. Events received from the broker are then processed by the local A2A instance, maintaining consistency across the distributed system. - -## Architecture - -The main components in the replicated queue manager are: - -- **[`ReplicatedQueueManager`](./core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java)**: Core queue manager that wraps the default `InMemoryQueueManager` and handles event replication. -- **[`ReplicationStrategy`](./core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java)**: Interface for different replication implementations. If `ReplicatedQueueManager` is used, a `ReplicationStrategy` **must** be provided. - -Currently, one implementation is provided: [`ReactiveMessagingReplicationStrategy`](./replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java), which uses MicroProfile Reactive Messaging with message brokers like Apache Kafka. - -## Quick Start - -This section will get you up and running quickly with a `ReplicatedQueueManager` using the `ReactiveMessagingReplicationStrategy` set up to use Kafka as the message broker. - -### 1. Add Dependencies - -#### Core Module (Required) - -Add the core replicated queue manager module to your project's `pom.xml`: - -```xml - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - ${a2a.version} - -``` - -The `ReplicatedQueueManager` is annotated in such a way that it should take precedence over the default `InMemoryQueueManager`. Hence, it is a drop-in replacement. - -#### Replication Strategy Implementation (Required) - -You must also include a replication strategy implementation. Currently, we provide one implementation using MicroProfile Reactive Messaging: - -```xml - - io.github.a2asdk - a2a-java-queue-manager-replication-mp-reactive - ${a2a.version} - -``` - -### 2. Basic Configuration - -Add to your `application.properties`: - -```properties -# Configure the outgoing channel (QueueManager -> Kafka) -mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka -mp.messaging.outgoing.replicated-events-out.topic=replicated-events -mp.messaging.outgoing.replicated-events-out.value.serializer=org.apache.kafka.common.serialization.StringSerializer - -# Configure the incoming channel (Kafka -> QueueManager) -mp.messaging.incoming.replicated-events-in.connector=smallrye-kafka -mp.messaging.incoming.replicated-events-in.topic=replicated-events -mp.messaging.incoming.replicated-events-in.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer -``` - -The channel names `replicated-events-in` and `replicated-events-out` correspond to the `@Incoming` and `@Channel` annotations in the ReactiveMessagingReplicationStrategy. - -### 3. Kafka Topic Setup - -Ensure your Kafka broker has the topic configured: - -```bash -# Create the replicated-events topic -kafka-topics.sh --create --topic replicated-events --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 -``` - -## Configuration - -### Kafka Configuration - -#### Basic Settings - -```properties -# Kafka broker configuration -kafka.bootstrap.servers=kafka-broker-1:9092,kafka-broker-2:9092 - -# Topic configuration -mp.messaging.outgoing.replicated-events-out.topic=my-replicated-events -mp.messaging.incoming.replicated-events-in.topic=my-replicated-events - -# Consumer behavior -mp.messaging.incoming.replicated-events-in.auto.offset.reset=earliest -``` - -#### Advanced Settings - -```properties -# Consumer group configuration (important for multiple A2A instances) -mp.messaging.incoming.replicated-events-in.group.id=a2a-instance-group - -# Reliability configuration -mp.messaging.outgoing.replicated-events-out.acks=all -mp.messaging.outgoing.replicated-events-out.retries=3 - -# Performance tuning -mp.messaging.outgoing.replicated-events-out.batch.size=16384 -mp.messaging.incoming.replicated-events-in.max.poll.records=500 - -# Serialization configuration -mp.messaging.outgoing.replicated-events-out.key.serializer=org.apache.kafka.common.serialization.StringSerializer -mp.messaging.incoming.replicated-events-in.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer -``` - -### Alternative Message Brokers - -While Kafka is the primary tested message broker, Quarkus Reactive Messaging supports other brokers: - -#### Apache Pulsar - -```properties -mp.messaging.outgoing.replicated-events-out.connector=smallrye-pulsar -mp.messaging.incoming.replicated-events-in.connector=smallrye-pulsar -pulsar.client.serviceUrl=pulsar://localhost:6650 -``` - -#### AMQP (RabbitMQ, etc.) - -```properties -mp.messaging.outgoing.replicated-events-out.connector=smallrye-amqp -mp.messaging.incoming.replicated-events-in.connector=smallrye-amqp -amqp-host=localhost -amqp-port=5672 -``` - -**Note**: Alternative message brokers have not been tested in this project yet. - -### WildFly/Jakarta EE Servers - -For non-Quarkus environments, you'll need to configure MicroProfile Reactive Messaging according to your application server's documentation. The exact configuration will depend on your server's messaging capabilities, but generally, you will need to make sure the same properties as above are made available to the server application. - -## How It Works - -### Event Flow - -1. **Event Generation**: When an event is generated in the A2A system (e.g., TaskStatusUpdateEvent), it's enqueued in the local queue -2. **Replication Hook**: The `ReplicationHook` intercepts the event and sends it to the replication strategy -3. **Message Broker**: The replication strategy serializes the event and sends it to the configured message broker -4. **Event Reception**: Other A2A instances receive the event from the message broker -5. **Local Processing**: The received event is deserialized and enqueued in the local instance's queue -6. **Event Processing**: The local instance processes the replicated event, updating its state accordingly - -### Event Types - -The system replicates various event types while preserving their specific types: - -- **TaskStatusUpdateEvent**: Task state changes (SUBMITTED, COMPLETED, etc.) -- **TaskArtifactUpdateEvent**: Task artifact changes -- **Message**: Chat messages and responses -- **Task**: Complete task objects -- **JSONRPCError**: Error events - -### Serialization - -Events are serialized using Jackson with polymorphic type information to ensure proper deserialization: - -```json -{ - "taskId": "task-123", - "event": { - "@type": "TaskStatusUpdateEvent", - "taskId": "task-123", - "status": { - "state": "completed", - "timestamp": "2023-09-29T10:30:00Z" - }, - "final": true, - "kind": "status-update" - } -} -``` - -## Production Considerations - -### Kafka Partitioning Strategy - -**Critical for scalability and correctness**: How you partition your Kafka topic significantly impacts system performance and behavior. - -#### Simple Approach: Single Partition - -The simplest configuration uses a single partition for the replicated events topic: - -```bash -kafka-topics.sh --create --topic replicated-events --bootstrap-server localhost:9092 --partitions 1 --replication-factor 1 -``` - -**Advantages**: -- Guarantees global event ordering -- Simpler to reason about and debug -- Suitable for development, testing, and low-throughput production systems - -**Disadvantages**: -- Limited scalability (single partition bottleneck) -- Cannot parallelize consumption across multiple consumer instances -- All events processed sequentially - -**When to use**: Development environments, integration tests, production systems with low event volumes (<1000 events/sec), or when strict global ordering is required. - -#### Recommended Approach: Partition by Task ID - -For production systems with higher throughput, partition events by `taskId`: - -```properties -# Configure the producer to use taskId as the partition key -mp.messaging.outgoing.replicated-events-out.key.serializer=org.apache.kafka.common.serialization.StringSerializer -mp.messaging.outgoing.replicated-events-out.value.serializer=org.apache.kafka.common.serialization.StringSerializer -``` - -```bash -# Create topic with multiple partitions -kafka-topics.sh --create --topic replicated-events --bootstrap-server localhost:9092 --partitions 10 --replication-factor 3 -``` - -The `ReactiveMessagingReplicationStrategy` already sends the `taskId` as the Kafka message key, so Kafka will automatically partition by task ID using its default partitioner. - -**Advantages**: -- **Horizontal scalability**: Different tasks can be processed in parallel across partitions -- **Per-task ordering guarantee**: All events for a single task go to the same partition and maintain order -- **Consumer parallelism**: Multiple consumer instances can process different partitions concurrently - -**Disadvantages**: -- No global ordering across all tasks -- More complex to debug (events spread across partitions) -- Requires proper consumer group configuration - -**When to use**: Production systems with medium to high throughput, systems that need to scale horizontally, distributed deployments with multiple A2A instances. - -#### Consumer Group Configuration - -When using multiple partitions, ensure all A2A instances belong to the same consumer group: - -```properties -mp.messaging.incoming.replicated-events-in.group.id=a2a-instance-group -``` - -This ensures that: -- Each partition is consumed by exactly one instance -- Events for the same task always go to the same instance (partition affinity) -- System can scale horizontally by adding more instances (up to the number of partitions) - -**Rule of thumb**: Number of partitions ≥ number of A2A instances for optimal distribution. - -### Transaction-Aware Queue Cleanup ("Poison Pill") - -When a task reaches a final state (COMPLETED, FAILED, CANCELED), all nodes in the cluster must terminate their event consumers for that task. This is achieved through a special "poison pill" event (`QueueClosedEvent`) that is replicated to all nodes. - -#### How It Works - -The poison pill mechanism uses **transaction-aware CDI events** to ensure the poison pill is only sent AFTER the final task state is durably committed to the database: - -1. **Task Finalization**: When `JpaDatabaseTaskStore.save()` persists a task with a final state, it fires a `TaskFinalizedEvent` CDI event -2. **Transaction Coordination**: The CDI observer is configured with `@Observes(during = TransactionPhase.AFTER_SUCCESS)`, which delays event delivery until AFTER the JPA transaction commits -3. **Poison Pill Delivery**: `ReplicatedQueueManager.onTaskFinalized()` receives the event and sends `QueueClosedEvent` via the replication strategy -4. **Cluster-Wide Termination**: All nodes receive the `QueueClosedEvent`, recognize it as final, and gracefully terminate their event consumers - -**Key Architecture Decision**: We use JPA transaction lifecycle hooks instead of time-based delays for poison pill delivery because: -- **Eliminates race conditions**: No time window where the poison pill might arrive before the database commit -- **Deterministic cleanup**: Queue termination happens immediately after transaction commit, without delay-based tuning -- **Simplicity**: No need to monitor consumer lag or configure delays for cleanup timing -- **Reliability**: Works correctly regardless of network latency or database performance - -**Note**: While the poison pill mechanism eliminates delays for cleanup, the system still uses a configurable grace period (`a2a.replication.grace-period-seconds`, default 15s) in `JpaDatabaseTaskStore.isTaskActive()` to handle late-arriving replicated events. This grace period prevents queue recreation for tasks that were recently finalized, accommodating Kafka consumer lag and network delays. See the Grace Period Configuration section below for details. - -#### Code Flow - -**JpaDatabaseTaskStore** (fires CDI event): -```java -@Inject -Event taskFinalizedEvent; - -public void save(Task task) { - // ... persist task to database ... - - // Fire CDI event if task reached final state - if (task.getStatus().state().isFinal()) { - taskFinalizedEvent.fire(new TaskFinalizedEvent(task.getId())); - } - // Transaction commits here (end of method) -} -``` - -**ReplicatedQueueManager** (observes and sends poison pill): -```java -public void onTaskFinalized(@Observes(during = TransactionPhase.AFTER_SUCCESS) TaskFinalizedEvent event) { - String taskId = event.getTaskId(); - LOGGER.debug("Task {} finalized - sending poison pill after transaction commit", taskId); - - // Send QueueClosedEvent to all nodes via replication - QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); - replicationStrategy.send(taskId, closedEvent); -} -``` - -#### Configuration - -No configuration is required for the poison pill mechanism - it works automatically when: -1. Using `JpaDatabaseTaskStore` for task persistence -2. Using `ReplicatedQueueManager` for event replication -3. Both modules are present in your application - -#### Monitoring - -Enable debug logging to monitor poison pill delivery: - -```properties -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG -``` - -You should see log entries like: -``` -Task abc-123 is in final state, firing TaskFinalizedEvent -Task abc-123 finalized - sending poison pill (QueueClosedEvent) after transaction commit -``` - -#### Grace Period Configuration - -While the poison pill mechanism provides deterministic cleanup timing, the system uses a configurable **grace period** to handle late-arriving replicated events. This is separate from the poison pill mechanism and serves a different purpose. - -**Purpose**: The grace period prevents queue recreation for tasks that were recently finalized. When a replicated event arrives after a task is finalized, the system checks if the task is still within the grace period before creating a new queue. - -**Configuration**: -```properties -# Grace period for handling late-arriving events (default: 15 seconds) -a2a.replication.grace-period-seconds=15 -``` - -**How It Works**: -1. When a task is finalized, `JpaDatabaseTaskStore` records the `finalizedAt` timestamp -2. When a replicated event arrives, `ReplicatedQueueManager.onReplicatedEvent()` calls `taskStateProvider.isTaskActive(taskId)` -3. `JpaDatabaseTaskStore.isTaskActive()` returns `true` if: - - Task is not in a final state, OR - - Task is final but within the grace period (`now < finalizedAt + gracePeriodSeconds`) -4. If `isTaskActive()` returns `false`, the replicated event is skipped (no queue created) - -**When to Adjust**: -- **Increase** the grace period if you observe warnings about skipped events for inactive tasks in high-latency networks -- **Decrease** the grace period to reduce memory usage in systems with very low latency and high task turnover -- **Default (15s)** is suitable for most deployments with typical Kafka consumer lag - -**Monitoring**: -```properties -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -``` - -Watch for: -``` -Skipping replicated event for inactive task abc-123 # Event arrived too late -``` - -**Important**: This grace period is for **late event handling**, not cleanup timing. The poison pill mechanism handles cleanup deterministically without delays. - -## Advanced Topics - -### Custom Replication Strategies - -The architecture is designed to support additional replication strategies in the future. To implement a custom replication strategy, create a class that implements the `ReplicationStrategy` interface and ensure it's discoverable via CDI: - -```java -@ApplicationScoped -public class CustomReplicationStrategy implements ReplicationStrategy { - - @Override - public void send(String taskId, Event event) { - // Implement custom replication logic - // e.g., send to database, REST API, etc. - } -} -``` - -### Monitoring Events - -You can monitor replicated events by observing CDI events: - -```java -@ApplicationScoped -public class ReplicationMonitor { - - public void onReplicatedEvent(@Observes ReplicatedEvent event) { - // Monitor replicated events for metrics, logging, etc. - LOGGER.info("Received replicated event for task: " + event.getTaskId()); - } -} -``` - -### Logging - -Enable debug logging to monitor replication activity: - -```properties -# For Quarkus -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG - -# For other servers, configure your logging framework accordingly -``` - -### Health Checks - -When using Quarkus, the module integrates with MicroProfile Health to provide health checks: - -```properties -# Configure health check timeout -quarkus.messaging.kafka.health.timeout=5s -``` diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml deleted file mode 100644 index cdb383d52..000000000 --- a/extras/queue-manager-replicated/core/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replicated-core - Java A2A Extras: Replicated Queue Manager Core - - - - io.github.a2asdk - a2a-java-sdk-server-common - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-jsonrpc-common - ${project.version} - - - io.github.a2asdk - a2a-java-extras-common - ${project.version} - - - io.quarkus - quarkus-core - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - org.junit.jupiter - junit-jupiter-api - test - - - ch.qos.logback - logback-classic - test - - - - \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java deleted file mode 100644 index 206e07f03..000000000 --- a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java +++ /dev/null @@ -1,171 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.core; - -import io.a2a.server.events.EventQueueItem; -import io.a2a.spec.A2AError; -import io.a2a.spec.Event; -import io.a2a.spec.StreamingEventKind; - -public class ReplicatedEventQueueItem implements EventQueueItem { - private String taskId; - - private StreamingEventKind event; - - private A2AError error; - - private boolean closedEvent; - - // Default constructor for JSON deserialization - public ReplicatedEventQueueItem() { - } - - // Constructor for creating from A2A StreamingEventKind objects - public ReplicatedEventQueueItem(String taskId, StreamingEventKind event) { - this.taskId = taskId; - this.event = event; - this.error = null; - } - - // Constructor for creating from A2A A2AError objects - public ReplicatedEventQueueItem(String taskId, A2AError error) { - this.taskId = taskId; - this.event = null; - this.error = error; - } - - // Backward compatibility constructor for generic Event objects - public ReplicatedEventQueueItem(String taskId, Event event) { - this.taskId = taskId; - if (event instanceof io.a2a.server.events.QueueClosedEvent) { - this.event = null; - this.error = null; - this.closedEvent = true; - } else if (event instanceof StreamingEventKind streamingEvent) { - this.event = streamingEvent; - this.error = null; - this.closedEvent = false; - } else if (event instanceof A2AError jsonRpcError) { - this.event = null; - this.error = jsonRpcError; - this.closedEvent = false; - } else { - throw new IllegalArgumentException("Event must be StreamingEventKind, A2AError, or QueueClosedEvent, got: " + event.getClass()); - } - } - - - public String getTaskId() { - return taskId; - } - - public void setTaskId(String taskId) { - this.taskId = taskId; - } - - /** - * Get the StreamingEventKind event field (for JSON serialization). - * @return the StreamingEventKind event or null - */ - public StreamingEventKind getStreamingEvent() { - return event; - } - - public void setEvent(StreamingEventKind event) { - this.event = event; - this.error = null; // Clear error when setting event - } - - /** - * Get the A2AError field (for JSON serialization). - * @return the A2AError or null - */ - public A2AError getErrorObject() { - return error; - } - - public void setError(A2AError error) { - this.error = error; - this.event = null; // Clear event when setting error - } - - /** - * Get the contained event as the generic Event interface (implements EventQueueItem). - * This is the method required by the EventQueueItem interface. - * @return the event (StreamingEventKind, A2AError, or QueueClosedEvent) or null if none is set - */ - @Override - public Event getEvent() { - if (closedEvent) { - return new io.a2a.server.events.QueueClosedEvent(taskId); - } - if (event != null) { - return event; - } - return error; - } - - /** - * Indicates this is a replicated event (implements EventQueueItem). - * @return always true for replicated events - */ - @Override - public boolean isReplicated() { - return true; - } - - /** - * Check if this ReplicatedEvent contains an event (vs an error). - * @return true if it contains a StreamingEventKind event - */ - public boolean hasEvent() { - return event != null; - } - - /** - * Check if this ReplicatedEvent contains an error. - * @return true if it contains a A2AError - */ - public boolean hasError() { - return error != null; - } - - /** - * Check if this is a QueueClosedEvent (poison pill). - * For JSON serialization. - * @return true if this is a queue closed event - */ - public boolean isClosedEvent() { - return closedEvent; - } - - /** - * Set the closed event flag (for JSON deserialization). - * @param closedEvent true if this is a queue closed event - */ - public void setClosedEvent(boolean closedEvent) { - this.closedEvent = closedEvent; - if (closedEvent) { - this.event = null; - this.error = null; - } - } - - /** - * Check if this event is a Task event. - * Task events should always be processed even for inactive tasks, - * as they carry the final task state. - * @return true if this is a Task event - */ - public boolean isTaskEvent() { - return event instanceof io.a2a.spec.Task; - } - - @Override - public String toString() { - return "ReplicatedEventQueueItem{" + - "taskId='" + taskId + '\'' + - ", event=" + event + - ", error=" + error + - ", closedEvent=" + closedEvent + - '}'; - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java deleted file mode 100644 index a5e3c629c..000000000 --- a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java +++ /dev/null @@ -1,228 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.core; - -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.event.Observes; -import jakarta.enterprise.event.TransactionPhase; -import jakarta.enterprise.inject.Alternative; -import jakarta.inject.Inject; - -import io.a2a.extras.common.events.TaskFinalizedEvent; -import io.a2a.server.events.EventEnqueueHook; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueFactory; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.TaskStateProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -@Alternative -@Priority(50) -public class ReplicatedQueueManager implements QueueManager { - private static final Logger LOGGER = LoggerFactory.getLogger(ReplicatedQueueManager.class); - - // Fields set by constructor injection cannot be final. We need a noargs constructor for - // Jakarta compatibility, and it seems that making fields set by constructor injection - // final, is not proxyable in all runtimes - private InMemoryQueueManager delegate; - private ReplicationStrategy replicationStrategy; - private TaskStateProvider taskStateProvider; - - /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. - */ - @SuppressWarnings("NullAway") - protected ReplicatedQueueManager() { - // For CDI proxy creation - this.delegate = null; - this.replicationStrategy = null; - this.taskStateProvider = null; - } - - @Inject - public ReplicatedQueueManager(ReplicationStrategy replicationStrategy, - TaskStateProvider taskStateProvider, - MainEventBus mainEventBus) { - this.replicationStrategy = replicationStrategy; - this.taskStateProvider = taskStateProvider; - this.delegate = new InMemoryQueueManager(new ReplicatingEventQueueFactory(), taskStateProvider, mainEventBus); - } - - - @Override - public void add(String taskId, EventQueue queue) { - delegate.add(taskId, queue); - } - - @Override - public EventQueue get(String taskId) { - return delegate.get(taskId); - } - - @Override - public EventQueue tap(String taskId) { - return delegate.tap(taskId); - } - - @Override - public void close(String taskId) { - // Close the local queue - this will trigger onClose callbacks - // The poison pill callback will check isTaskFinalized() and send if needed - // The cleanup callback will remove the queue from the map - delegate.close(taskId); - } - - @Override - public EventQueue createOrTap(String taskId) { - return delegate.createOrTap(taskId); - } - - @Override - public void awaitQueuePollerStart(EventQueue eventQueue) throws InterruptedException { - delegate.awaitQueuePollerStart(eventQueue); - } - - public void onReplicatedEvent(@Observes ReplicatedEventQueueItem replicatedEvent) { - // Check if task is still active before processing replicated event - // Always allow QueueClosedEvent and Task events (they carry final state) - // Skip other event types for inactive tasks to prevent queue creation for expired tasks - if (!replicatedEvent.isClosedEvent() - && !replicatedEvent.isTaskEvent() - && !taskStateProvider.isTaskActive(replicatedEvent.getTaskId())) { - // Task is no longer active - skip processing this replicated event - // This prevents creating queues for tasks that have been finalized beyond the grace period - LOGGER.debug("Skipping replicated event for inactive task {}", replicatedEvent.getTaskId()); - return; - } - - // Get the MainQueue to enqueue the replicated event item - // We must use enqueueItem (not enqueueEvent) to preserve the isReplicated() flag - // and avoid triggering the replication hook again (which would cause a replication loop) - // - // IMPORTANT: We must NOT create a ChildQueue here! Creating and immediately closing - // a ChildQueue means there are zero children when MainEventBusProcessor distributes - // the event. Existing ChildQueues (from active client subscriptions) will receive - // the event when MainEventBusProcessor distributes it to all children. - // - // If MainQueue doesn't exist, create it. This handles late-arriving replicated events - // for tasks that were created on another instance. - EventQueue childQueue = null; // Track ChildQueue we might create - EventQueue mainQueue = delegate.get(replicatedEvent.getTaskId()); - try { - if (mainQueue == null) { - LOGGER.debug("Creating MainQueue for replicated event on task {}", replicatedEvent.getTaskId()); - childQueue = delegate.createOrTap(replicatedEvent.getTaskId()); // Creates MainQueue + returns ChildQueue - mainQueue = delegate.get(replicatedEvent.getTaskId()); // Get MainQueue from map - } - - if (mainQueue != null) { - mainQueue.enqueueItem(replicatedEvent); - } else { - LOGGER.warn( - "MainQueue not found for task {}, cannot enqueue replicated event. This may happen if the queue was already cleaned up.", - replicatedEvent.getTaskId()); - } - } finally { - if (childQueue != null) { - try { - childQueue.close(); // Close the ChildQueue we created (not MainQueue!) - } catch (Exception ignore) { - // The close is safe, but print a stacktrace just in case - if (LOGGER.isDebugEnabled()) { - ignore.printStackTrace(); - } - } - } - } - } - - /** - * Observes task finalization events fired AFTER database transaction commits. - * This guarantees the task's final state is durably stored before replication. - * - * Sends TaskStatusUpdateEvent (not full Task) FIRST, then the poison pill (QueueClosedEvent), - * ensuring correct event ordering across instances and eliminating race conditions where - * the poison pill arrives before the final task state. - * - * IMPORTANT: We send TaskStatusUpdateEvent instead of full Task to maintain consistency - * with local event distribution. Clients expect TaskStatusUpdateEvent for status changes, - * and sending the full Task causes issues in remote instances where clients don't handle - * bare Task objects the same way they handle TaskStatusUpdateEvent. - * - * @param event the task finalized event containing the task ID and final Task - */ - public void onTaskFinalized(@Observes(during = TransactionPhase.AFTER_SUCCESS) TaskFinalizedEvent event) { - String taskId = event.getTaskId(); - io.a2a.spec.Task finalTask = (io.a2a.spec.Task) event.getTask(); // Cast from Object - - LOGGER.debug("Task {} finalized - sending TaskStatusUpdateEvent then poison pill (QueueClosedEvent) after transaction commit", taskId); - - // Convert final Task to TaskStatusUpdateEvent to match local event distribution - // This ensures remote instances receive the same event type as local instances - io.a2a.spec.TaskStatusUpdateEvent finalStatusEvent = io.a2a.spec.TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId(finalTask.contextId()) - .status(finalTask.status()) - .build(); - - // Send TaskStatusUpdateEvent FIRST to ensure it arrives before poison pill - replicationStrategy.send(taskId, finalStatusEvent); - - // Then send poison pill - // The transaction has committed, so the final state is guaranteed to be in the database - io.a2a.server.events.QueueClosedEvent closedEvent = new io.a2a.server.events.QueueClosedEvent(taskId); - replicationStrategy.send(taskId, closedEvent); - } - - @Override - public EventQueue.EventQueueBuilder getEventQueueBuilder(String taskId) { - return QueueManager.super.getEventQueueBuilder(taskId) - .hook(new ReplicationHook(taskId)); - } - - @Override - public int getActiveChildQueueCount(String taskId) { - return delegate.getActiveChildQueueCount(taskId); - } - - private class ReplicatingEventQueueFactory implements EventQueueFactory { - @Override - public EventQueue.EventQueueBuilder builder(String taskId) { - // Poison pill sending is handled by the TaskFinalizedEvent observer (onTaskFinalized) - // which sends the QueueClosedEvent after the database transaction commits. - // This ensures proper ordering and transactional guarantees. - - // Call createBaseEventQueueBuilder() directly to avoid infinite recursion - // (getEventQueueBuilder() would delegate back to this factory, creating a loop) - // The base builder already includes: taskId, cleanup callback, taskStateProvider, mainEventBus - return delegate.createBaseEventQueueBuilder(taskId) - .hook(new ReplicationHook(taskId)); - } - } - - - private class ReplicationHook implements EventEnqueueHook { - private final String taskId; - - public ReplicationHook(String taskId) { - this.taskId = taskId; - } - - @Override - public void onEnqueue(EventQueueItem item) { - if (!item.isReplicated()) { - // Only replicate if this isn't already a replicated event - // This prevents replication loops - if (taskId != null) { - replicationStrategy.send(taskId, item.getEvent()); - } - } - } - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java deleted file mode 100644 index fed85db64..000000000 --- a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicationStrategy.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.core; - -import io.a2a.spec.Event; - -public interface ReplicationStrategy { - void send(String taskId, Event event); -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/main/resources/META-INF/beans.xml b/extras/queue-manager-replicated/core/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 6bb944ce2..000000000 --- a/extras/queue-manager-replicated/core/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java b/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java deleted file mode 100644 index 04fa5d024..000000000 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java +++ /dev/null @@ -1,331 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.core; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; - -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.events.QueueClosedEvent; -import io.a2a.spec.A2AError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.Message; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -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; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; -import org.junit.jupiter.api.Test; - -/** - * Comprehensive test for serialization/deserialization of all StreamingEventKind classes - * and A2AError subclasses to ensure proper type handling in replication. - */ -public class EventSerializationTest { - - @Test - public void testTaskSerialization() throws JsonProcessingException { - // Create a Task - TaskStatus status = new TaskStatus(TaskState.TASK_STATE_SUBMITTED); - Task originalTask = Task.builder() - .id("test-task-123") - .contextId("test-context-456") - .status(status) - .build(); - - // Test serialization as Event - String json = JsonUtil.toJson(originalTask); - assertTrue(json.contains("\"task\""), "JSON should contain task wrapper"); - assertTrue(json.contains("\"id\":\"test-task-123\""), "JSON should contain task ID"); - - // Test deserialization back to StreamingEventKind - StreamingEventKind deserializedEvent = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(Task.class, deserializedEvent, "Should deserialize to Task"); - - Task deserializedTask = (Task) deserializedEvent; - assertEquals(originalTask.id(), deserializedTask.id()); - assertEquals(originalTask.kind(), deserializedTask.kind()); - assertEquals(originalTask.contextId(), deserializedTask.contextId()); - assertEquals(originalTask.status().state(), deserializedTask.status().state()); - - // Test as StreamingEventKind - StreamingEventKind deserializedAsStreaming = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(Task.class, deserializedAsStreaming, "Should deserialize to Task as StreamingEventKind"); - } - - @Test - public void testMessageSerialization() throws JsonProcessingException { - // Create a Message - Message originalMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("Hello, world!"))) - .taskId("test-task-789") - .messageId("test-msg-456") - .contextId("test-context-123") - .build(); - - // Test serialization as Event - String json = JsonUtil.toJson(originalMessage); - assertTrue(json.contains("\"message\""), "JSON should contain message wrapper"); - assertTrue(json.contains("\"taskId\":\"test-task-789\""), "JSON should contain task ID"); - - // Test deserialization back to StreamingEventKind - StreamingEventKind deserializedEvent = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(Message.class, deserializedEvent, "Should deserialize to Message"); - - Message deserializedMessage = (Message) deserializedEvent; - assertEquals(originalMessage.taskId(), deserializedMessage.taskId()); - assertEquals(originalMessage.kind(), deserializedMessage.kind()); - assertEquals(originalMessage.role(), deserializedMessage.role()); - assertEquals(originalMessage.parts().size(), deserializedMessage.parts().size()); - - // Test as StreamingEventKind - StreamingEventKind deserializedAsStreaming = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(Message.class, deserializedAsStreaming, "Should deserialize to Message as StreamingEventKind"); - } - - @Test - public void testTaskStatusUpdateEventSerialization() throws JsonProcessingException { - // Create a TaskStatusUpdateEvent - TaskStatus status = new TaskStatus(TaskState.TASK_STATE_COMPLETED); - TaskStatusUpdateEvent originalEvent = TaskStatusUpdateEvent.builder() - .taskId("test-task-abc") - .contextId("test-context-def") - .status(status) - .build(); - - // Test serialization as Event - String json = JsonUtil.toJson((Event) originalEvent); - assertTrue(json.contains("\"statusUpdate\""), "JSON should contain statusUpdate wrapper"); - assertTrue(json.contains("\"taskId\":\"test-task-abc\""), "JSON should contain task ID"); - assertTrue(json.contains("\"final\":true"), "JSON should contain final flag"); - - // Test deserialization back to StreamingEventKind - StreamingEventKind deserializedEvent = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(TaskStatusUpdateEvent.class, deserializedEvent, "Should deserialize to TaskStatusUpdateEvent"); - - TaskStatusUpdateEvent deserializedStatusEvent = (TaskStatusUpdateEvent) deserializedEvent; - assertEquals(originalEvent.taskId(), deserializedStatusEvent.taskId()); - assertEquals(originalEvent.kind(), deserializedStatusEvent.kind()); - assertEquals(originalEvent.contextId(), deserializedStatusEvent.contextId()); - assertEquals(originalEvent.status().state(), deserializedStatusEvent.status().state()); - assertEquals(originalEvent.isFinal(), deserializedStatusEvent.isFinal()); - - // Test as StreamingEventKind - StreamingEventKind deserializedAsStreaming = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(TaskStatusUpdateEvent.class, deserializedAsStreaming, "Should deserialize to TaskStatusUpdateEvent as StreamingEventKind"); - } - - @Test - public void testTaskArtifactUpdateEventSerialization() throws JsonProcessingException { - // Create a TaskArtifactUpdateEvent - List> parts = List.of(new TextPart("Test artifact content")); - Artifact artifact = new Artifact("test-artifact-123", "Test Artifact", "Test description", parts, null, null); - TaskArtifactUpdateEvent originalEvent = TaskArtifactUpdateEvent.builder() - .taskId("test-task-xyz") - .contextId("test-context-uvw") - .artifact(artifact) - .build(); - - // Test serialization as Event - String json = JsonUtil.toJson((Event) originalEvent); - assertTrue(json.contains("\"artifactUpdate\""), "JSON should contain artifactUpdate wrapper"); - assertTrue(json.contains("\"taskId\":\"test-task-xyz\""), "JSON should contain task ID"); - assertTrue(json.contains("\"test-artifact-123\""), "JSON should contain artifact ID"); - - // Test deserialization back to StreamingEventKind - StreamingEventKind deserializedEvent = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(TaskArtifactUpdateEvent.class, deserializedEvent, "Should deserialize to TaskArtifactUpdateEvent"); - - TaskArtifactUpdateEvent deserializedArtifactEvent = (TaskArtifactUpdateEvent) deserializedEvent; - assertEquals(originalEvent.taskId(), deserializedArtifactEvent.taskId()); - assertEquals(originalEvent.kind(), deserializedArtifactEvent.kind()); - assertEquals(originalEvent.contextId(), deserializedArtifactEvent.contextId()); - assertEquals(originalEvent.artifact().artifactId(), deserializedArtifactEvent.artifact().artifactId()); - assertEquals(originalEvent.artifact().name(), deserializedArtifactEvent.artifact().name()); - - // Test as StreamingEventKind - StreamingEventKind deserializedAsStreaming = JsonUtil.fromJson(json, StreamingEventKind.class); - assertInstanceOf(TaskArtifactUpdateEvent.class, deserializedAsStreaming, "Should deserialize to TaskArtifactUpdateEvent as StreamingEventKind"); - } - - @Test - public void testA2AErrorSubclassesSerialization() throws JsonProcessingException { - // Test various A2AError subclasses - A2AError[] errors = { - new InvalidRequestError("Invalid request"), - new MethodNotFoundError(), - new InvalidParamsError("Invalid params"), - new InternalError("Internal error"), - new JSONParseError("Parse error"), - new TaskNotFoundError(), - new TaskNotCancelableError(), - new UnsupportedOperationError(), - new PushNotificationNotSupportedError() - // Note: ContentTypeNotSupportedError and InvalidAgentResponseError need specific constructor parameters - }; - - for (A2AError originalError : errors) { - // Test serialization - String json = JsonUtil.toJson(originalError); - assertTrue(json.contains("\"message\""), "JSON should contain error message for " + originalError.getClass().getSimpleName()); - - // Test deserialization - it's acceptable to deserialize as base A2AError - A2AError deserializedError = JsonUtil.fromJson(json, A2AError.class); - assertNotNull(deserializedError, "Should deserialize successfully for " + originalError.getClass().getSimpleName()); - assertEquals(originalError.getMessage(), deserializedError.getMessage(), "Error message should match for " + originalError.getClass().getSimpleName()); - assertEquals(originalError.getCode(), deserializedError.getCode(), "Error code should match for " + originalError.getClass().getSimpleName()); - - // The deserialized error might be the base class, which is acceptable per the requirements - } - } - - @Test - public void testReplicatedEventWithStreamingEventSerialization() throws JsonProcessingException { - // Test that ReplicatedEventQueueItem can properly handle StreamingEventKind - TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() - .taskId("replicated-test-task") - .contextId("replicated-test-context") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - // Create ReplicatedEventQueueItem with StreamingEventKind - ReplicatedEventQueueItem originalReplicatedEvent = new ReplicatedEventQueueItem("replicated-test-task", statusEvent); - - // Serialize the ReplicatedEventQueueItem - String json = JsonUtil.toJson(originalReplicatedEvent); - assertTrue(json.contains("\"taskId\":\"replicated-test-task\""), "JSON should contain task ID"); - assertTrue(json.contains("\"event\""), "JSON should contain event field"); - assertTrue(json.contains("\"statusUpdate\""), "JSON should contain the event type wrapper"); - assertFalse(json.contains("\"error\""), "JSON should not contain error field"); - - // Deserialize the ReplicatedEventQueueItem - ReplicatedEventQueueItem deserializedReplicatedEvent = JsonUtil.fromJson(json, ReplicatedEventQueueItem.class); - assertEquals(originalReplicatedEvent.getTaskId(), deserializedReplicatedEvent.getTaskId()); - - // Now we should get the proper type back! - Event retrievedEventAsEvent = deserializedReplicatedEvent.getEvent(); - assertNotNull(retrievedEventAsEvent); - assertInstanceOf(TaskStatusUpdateEvent.class, retrievedEventAsEvent, "Should deserialize to TaskStatusUpdateEvent"); - - TaskStatusUpdateEvent retrievedStatusEvent = (TaskStatusUpdateEvent) retrievedEventAsEvent; - assertEquals(statusEvent.taskId(), retrievedStatusEvent.taskId()); - assertEquals(statusEvent.contextId(), retrievedStatusEvent.contextId()); - assertEquals(statusEvent.status().state(), retrievedStatusEvent.status().state()); - assertEquals(statusEvent.isFinal(), retrievedStatusEvent.isFinal()); - - // Test helper methods - assertTrue(deserializedReplicatedEvent.hasEvent()); - assertFalse(deserializedReplicatedEvent.hasError()); - assertFalse(deserializedReplicatedEvent.isClosedEvent()); - assertNull(deserializedReplicatedEvent.getErrorObject()); - } - - @Test - public void testReplicatedEventWithErrorSerialization() throws JsonProcessingException { - // Test that ReplicatedEventQueueItem can properly handle A2AError - InvalidRequestError error = new InvalidRequestError("Invalid request for testing"); - - // Create ReplicatedEventQueueItem with A2AError - ReplicatedEventQueueItem originalReplicatedEvent = new ReplicatedEventQueueItem("error-test-task", error); - - // Serialize the ReplicatedEventQueueItemQueueItem - String json = JsonUtil.toJson(originalReplicatedEvent); - assertTrue(json.contains("\"taskId\":\"error-test-task\""), "JSON should contain task ID"); - assertTrue(json.contains("\"error\""), "JSON should contain error field"); - assertTrue(json.contains("\"message\""), "JSON should contain error message"); - assertFalse(json.contains("\"event\""), "JSON should not contain event field"); - - // Deserialize the ReplicatedEventQueueItem - ReplicatedEventQueueItem deserializedReplicatedEvent = JsonUtil.fromJson(json, ReplicatedEventQueueItem.class); - assertEquals(originalReplicatedEvent.getTaskId(), deserializedReplicatedEvent.getTaskId()); - - // Should get the error back - A2AError retrievedError = deserializedReplicatedEvent.getErrorObject(); - assertNotNull(retrievedError); - assertEquals(error.getMessage(), retrievedError.getMessage()); - assertEquals(error.getCode(), retrievedError.getCode()); - - // Test helper methods - assertFalse(deserializedReplicatedEvent.hasEvent()); - assertTrue(deserializedReplicatedEvent.hasError()); - assertFalse(deserializedReplicatedEvent.isClosedEvent()); - assertNull(deserializedReplicatedEvent.getStreamingEvent()); - } - - @Test - public void testReplicatedEventBackwardCompatibility() throws JsonProcessingException { - // Test backward compatibility with generic Event constructor - TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() - .taskId("backward-compat-task") - .contextId("backward-compat-context") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - // Use the backward compatibility constructor - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem("backward-compat-task", (Event) statusEvent); - - // Should work the same as the specific constructor - assertTrue(replicatedEvent.hasEvent()); - assertFalse(replicatedEvent.hasError()); - assertFalse(replicatedEvent.isClosedEvent()); - assertInstanceOf(TaskStatusUpdateEvent.class, replicatedEvent.getEvent()); - } - - @Test - public void testQueueClosedEventSerialization() throws JsonProcessingException { - // Test that QueueClosedEvent can be properly serialized and deserialized via ReplicatedEventQueueItem - String taskId = "queue-closed-serialization-test"; - QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); - - // Create ReplicatedEventQueueItem with QueueClosedEvent - ReplicatedEventQueueItem originalReplicatedEvent = new ReplicatedEventQueueItem(taskId, closedEvent); - - // Verify the item is marked as a closed event - assertTrue(originalReplicatedEvent.isClosedEvent(), "Should be marked as closed event"); - assertFalse(originalReplicatedEvent.hasEvent(), "Should not have regular event"); - assertFalse(originalReplicatedEvent.hasError(), "Should not have error"); - - // Serialize the ReplicatedEventQueueItem - String json = JsonUtil.toJson(originalReplicatedEvent); - assertTrue(json.contains("\"taskId\":\"" + taskId + "\""), "JSON should contain task ID"); - assertTrue(json.contains("\"closedEvent\":true"), "JSON should contain closedEvent flag set to true"); - assertFalse(json.contains("\"event\""), "JSON should not contain event field"); - assertFalse(json.contains("\"error\""), "JSON should not contain error field"); - - // Deserialize the ReplicatedEventQueueItem - ReplicatedEventQueueItem deserializedReplicatedEvent = JsonUtil.fromJson(json, ReplicatedEventQueueItem.class); - assertEquals(taskId, deserializedReplicatedEvent.getTaskId()); - - // Verify the deserialized item is marked as a closed event - assertTrue(deserializedReplicatedEvent.isClosedEvent(), "Deserialized should be marked as closed event"); - assertFalse(deserializedReplicatedEvent.hasEvent(), "Deserialized should not have regular event"); - assertFalse(deserializedReplicatedEvent.hasError(), "Deserialized should not have error"); - - // Verify getEvent() reconstructs the QueueClosedEvent - Event retrievedEvent = deserializedReplicatedEvent.getEvent(); - assertNotNull(retrievedEvent, "getEvent() should return a reconstructed QueueClosedEvent"); - assertInstanceOf(QueueClosedEvent.class, retrievedEvent, "Should deserialize to QueueClosedEvent"); - - QueueClosedEvent retrievedClosedEvent = (QueueClosedEvent) retrievedEvent; - assertEquals(taskId, retrievedClosedEvent.getTaskId(), "Reconstructed event should have correct task ID"); - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java b/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java deleted file mode 100644 index 7c830fb64..000000000 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java +++ /dev/null @@ -1,690 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.core; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import io.a2a.extras.common.events.TaskFinalizedEvent; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueClosedException; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.EventQueueTestHelper; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.events.QueueClosedEvent; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.Event; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class ReplicatedQueueManagerTest { - - private ReplicatedQueueManager queueManager; - private StreamingEventKind testEvent; - private MainEventBus mainEventBus; - private MainEventBusProcessor mainEventBusProcessor; - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; - - @BeforeEach - void setUp() { - // Create MainEventBus first - InMemoryTaskStore taskStore = new InMemoryTaskStore(); - mainEventBus = new MainEventBus(); - - // Create QueueManager before MainEventBusProcessor (processor needs it as parameter) - queueManager = new ReplicatedQueueManager( - new NoOpReplicationStrategy(), - new MockTaskStateProvider(true), - mainEventBus - ); - - // Create MainEventBusProcessor with QueueManager - mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); - EventQueueUtil.start(mainEventBusProcessor); - - testEvent = TaskStatusUpdateEvent.builder() - .taskId("test-task") - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - } - - /** - * Helper to create a test event with the specified taskId. - * This ensures taskId consistency between queue creation and event creation. - */ - private TaskStatusUpdateEvent createEventForTask(String taskId) { - return TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - } - - @AfterEach - void tearDown() { - if (mainEventBusProcessor != null) { - mainEventBusProcessor.setCallback(null); // Clear any test callbacks - EventQueueUtil.stop(mainEventBusProcessor); - } - mainEventBusProcessor = null; - mainEventBus = null; - queueManager = null; - } - - /** - * Helper to wait for MainEventBusProcessor to process an event. - * Replaces polling patterns with deterministic callback-based waiting. - * - * @param action the action that triggers event processing - * @throws InterruptedException if waiting is interrupted - * @throws AssertionError if processing doesn't complete within timeout - */ - private void waitForEventProcessing(Runnable action) throws InterruptedException { - CountDownLatch processingLatch = new CountDownLatch(1); - mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { - @Override - public void onEventProcessed(String taskId, io.a2a.spec.Event event) { - processingLatch.countDown(); - } - - @Override - public void onTaskFinalized(String taskId) { - // Not needed for basic event processing wait - } - }); - - try { - action.run(); - assertTrue(processingLatch.await(5, TimeUnit.SECONDS), - "MainEventBusProcessor should have processed the event within timeout"); - } finally { - mainEventBusProcessor.setCallback(null); - } - } - - @Test - void testReplicationStrategyTriggeredOnNormalEnqueue() throws InterruptedException { - CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); - - String taskId = "test-task-1"; - EventQueue queue = queueManager.createOrTap(taskId); - TaskStatusUpdateEvent event = createEventForTask(taskId); - - // Wait for MainEventBusProcessor to process the event and trigger replication - waitForEventProcessing(() -> queue.enqueueEvent(event)); - - assertEquals(1, strategy.getCallCount()); - assertEquals(taskId, strategy.getLastTaskId()); - assertEquals(event, strategy.getLastEvent()); - } - - @Test - void testReplicationStrategyNotTriggeredOnReplicatedEvent() throws InterruptedException { - CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); - - String taskId = "test-task-2"; - EventQueue queue = queueManager.createOrTap(taskId); - - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, getTaskStatusUpdateEventWithNewId(taskId)); - queueManager.onReplicatedEvent(replicatedEvent); - - assertEquals(0, strategy.getCallCount()); - } - - @Test - void testReplicationStrategyWithCountingImplementation() throws InterruptedException { - CountingReplicationStrategy countingStrategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(countingStrategy, new MockTaskStateProvider(true), mainEventBus); - - String taskId = "test-task-3"; - EventQueue queue = queueManager.createOrTap(taskId); - TaskStatusUpdateEvent event = createEventForTask(taskId); - - // Wait for MainEventBusProcessor to process each event - waitForEventProcessing(() -> queue.enqueueEvent(event)); - waitForEventProcessing(() -> queue.enqueueEvent(event)); - - assertEquals(2, countingStrategy.getCallCount()); - assertEquals(taskId, countingStrategy.getLastTaskId()); - assertEquals(event, countingStrategy.getLastEvent()); - - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, getTaskStatusUpdateEventWithNewId(taskId)); - queueManager.onReplicatedEvent(replicatedEvent); - - assertEquals(2, countingStrategy.getCallCount()); - } - - @Test - void testReplicatedEventDeliveredToCorrectQueue() throws InterruptedException { - String taskId = "test-task-4"; - TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId - EventQueue queue = queueManager.createOrTap(taskId); - - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, eventForTask); - - // Use callback to wait for event processing - EventQueueItem item = dequeueEventWithRetry(queue, () -> queueManager.onReplicatedEvent(replicatedEvent)); - assertNotNull(item, "Event should be available in queue"); - Event dequeuedEvent = item.getEvent(); - assertEquals(eventForTask, dequeuedEvent); - } - - @Test - void testReplicatedEventCreatesQueueIfNeeded() throws InterruptedException { - String taskId = "non-existent-task"; - TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId - - // Verify no queue exists initially - assertNull(queueManager.get(taskId)); - - // Create a ChildQueue BEFORE processing the replicated event - // This ensures the ChildQueue exists when MainEventBusProcessor distributes the event - EventQueue childQueue = queueManager.createOrTap(taskId); - assertNotNull(childQueue, "ChildQueue should be created"); - - // Verify MainQueue was created - EventQueue mainQueue = queueManager.get(taskId); - assertNotNull(mainQueue, "MainQueue should exist after createOrTap"); - - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, eventForTask); - - // Process the replicated event and wait for distribution - // Use callback to wait for event processing - EventQueueItem item = dequeueEventWithRetry(childQueue, () -> { - assertDoesNotThrow(() -> queueManager.onReplicatedEvent(replicatedEvent)); - }); - assertNotNull(item, "Event should be available in queue"); - Event dequeuedEvent = item.getEvent(); - assertEquals(eventForTask, dequeuedEvent, "The replicated event should be enqueued in the newly created queue"); - } - - @Test - void testBasicQueueManagerFunctionality() throws InterruptedException { - String taskId = "test-task-5"; - - assertNull(queueManager.get(taskId)); - assertNull(queueManager.tap(taskId)); - - EventQueue queue = queueManager.createOrTap(taskId); - assertNotNull(queue); - - // createOrTap now returns ChildQueue, get returns MainQueue - EventQueue retrievedQueue = queueManager.get(taskId); - assertNotNull(retrievedQueue); - // queue should be a ChildQueue (cannot be tapped) - assertThrows(IllegalStateException.class, () -> EventQueueTestHelper.tapQueue(queue)); - - EventQueue tappedQueue = queueManager.tap(taskId); - assertNotNull(tappedQueue); - assertNotEquals(queue, tappedQueue); - - queueManager.close(taskId); - assertNull(queueManager.get(taskId)); - } - - @Test - void testQueueToTaskIdMappingMaintained() throws InterruptedException { - String taskId = "test-task-6"; - CountingReplicationStrategy countingStrategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(countingStrategy, new MockTaskStateProvider(true), mainEventBus); - TaskStatusUpdateEvent event = createEventForTask(taskId); - - EventQueue queue = queueManager.createOrTap(taskId); - waitForEventProcessing(() -> queue.enqueueEvent(event)); - - assertEquals(taskId, countingStrategy.getLastTaskId()); - - queueManager.close(taskId); // Task is active, so NO poison pill is sent - - EventQueue newQueue = queueManager.createOrTap(taskId); - waitForEventProcessing(() -> newQueue.enqueueEvent(event)); - - assertEquals(taskId, countingStrategy.getLastTaskId()); - // 2 replication calls: 1 testEvent, 1 testEvent (no QueueClosedEvent because task is active) - assertEquals(2, countingStrategy.getCallCount()); - } - - @Test - void testReplicatedEventJsonSerialization() throws Exception { - // Test that ReplicatedEventQueueItem can be properly serialized and deserialized with StreamingEventKind - TaskStatusUpdateEvent originalEvent = TaskStatusUpdateEvent.builder() - .taskId("json-test-task") - .contextId("json-test-context") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - ReplicatedEventQueueItem original = new ReplicatedEventQueueItem("json-test-task", originalEvent); - - // Serialize to JSON - String json = JsonUtil.toJson(original); - assertNotNull(json); - assertTrue(json.contains("json-test-task")); - assertTrue(json.contains("\"event\":{")); - assertTrue(json.contains("\"statusUpdate\"")); - - // Deserialize back - ReplicatedEventQueueItem deserialized = JsonUtil.fromJson(json, ReplicatedEventQueueItem.class); - assertNotNull(deserialized); - assertEquals("json-test-task", deserialized.getTaskId()); - assertNotNull(deserialized.getEvent()); - assertTrue(deserialized.hasEvent()); - assertFalse(deserialized.hasError()); - } - - @Test - void testParallelReplicationBehavior() throws InterruptedException { - CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); - - String taskId = "parallel-test-task"; - EventQueue queue = queueManager.createOrTap(taskId); - - int numThreads = 10; - int eventsPerThread = 5; - int expectedEventCount = (numThreads / 2) * eventsPerThread; // Only normal enqueues - int totalEventCount = numThreads * eventsPerThread; // All events (normal + replicated) - ExecutorService executor = Executors.newFixedThreadPool(numThreads); - CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch doneLatch = new CountDownLatch(numThreads); - - // Use CyclicBarrier for better thread synchronization - // This ensures all threads start their work at approximately the same time - java.util.concurrent.CyclicBarrier barrier = new java.util.concurrent.CyclicBarrier(numThreads); - - // Track processed events for better diagnostics on failure - java.util.concurrent.CopyOnWriteArrayList processedEvents = - new java.util.concurrent.CopyOnWriteArrayList<>(); - - // Set up callback to wait for ALL events to be processed by MainEventBusProcessor - // Must wait for all 50 events (25 normal + 25 replicated) to ensure all normal events - // have triggered replication before we check the count - CountDownLatch processingLatch = new CountDownLatch(totalEventCount); - mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { - @Override - public void onEventProcessed(String tid, io.a2a.spec.Event event) { - processedEvents.add(event); - processingLatch.countDown(); - } - - @Override - public void onTaskFinalized(String tid) { - // Not needed for this test - } - }); - - // Launch threads that will enqueue events normally (should trigger replication) - for (int i = 0; i < numThreads / 2; i++) { - final int threadId = i; - executor.submit(() -> { - try { - startLatch.await(); - barrier.await(); // Synchronize thread starts for better interleaving - for (int j = 0; j < eventsPerThread; j++) { - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(taskId) // Use same taskId as queue - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - queue.enqueueEvent(event); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (java.util.concurrent.BrokenBarrierException e) { - throw new RuntimeException("Barrier broken", e); - } finally { - doneLatch.countDown(); - } - }); - } - - // Launch threads that will send replicated events (should NOT trigger replication) - for (int i = numThreads / 2; i < numThreads; i++) { - final int threadId = i; - executor.submit(() -> { - try { - startLatch.await(); - barrier.await(); // Synchronize thread starts for better interleaving - for (int j = 0; j < eventsPerThread; j++) { - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(taskId) // Use same taskId as queue - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); - queueManager.onReplicatedEvent(replicatedEvent); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (java.util.concurrent.BrokenBarrierException e) { - throw new RuntimeException("Barrier broken", e); - } finally { - doneLatch.countDown(); - } - }); - } - - // Start all threads simultaneously - startLatch.countDown(); - - // Wait for all threads to complete with explicit timeout - assertTrue(doneLatch.await(10, TimeUnit.SECONDS), - "All " + numThreads + " threads should complete within 10 seconds"); - - executor.shutdown(); - assertTrue(executor.awaitTermination(5, TimeUnit.SECONDS), - "Executor should shutdown within 5 seconds"); - - // Wait for MainEventBusProcessor to process all events - try { - boolean allProcessed = processingLatch.await(10, TimeUnit.SECONDS); - assertTrue(allProcessed, - String.format("MainEventBusProcessor should have processed all %d events within timeout. " + - "Processed: %d, Remaining: %d", - totalEventCount, processedEvents.size(), processingLatch.getCount())); - } finally { - mainEventBusProcessor.setCallback(null); - queue.close(true, true); - } - - // Verify we processed the expected number of events - assertEquals(totalEventCount, processedEvents.size(), - "Should have processed exactly " + totalEventCount + " events (normal + replicated)"); - - // Only the normal enqueue operations should have triggered replication - // numThreads/2 threads * eventsPerThread events each = total expected replication calls - int expectedReplicationCalls = (numThreads / 2) * eventsPerThread; - assertEquals(expectedReplicationCalls, strategy.getCallCount(), - String.format("Only normal enqueue operations should trigger replication, not replicated events. " + - "Expected: %d, Actual: %d", expectedReplicationCalls, strategy.getCallCount())); - } - - @Test - void testReplicatedEventSkippedWhenTaskInactive() throws InterruptedException { - // Create a task state provider that returns false (task is inactive) - MockTaskStateProvider stateProvider = new MockTaskStateProvider(false); - queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider, mainEventBus); - - String taskId = "inactive-task"; - - // Verify no queue exists initially - assertNull(queueManager.get(taskId)); - - // Process a replicated event for an inactive task - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, testEvent); - queueManager.onReplicatedEvent(replicatedEvent); - - // Queue should NOT be created because task is inactive - assertNull(queueManager.get(taskId), "Queue should not be created for inactive task"); - } - - @Test - void testReplicatedEventProcessedWhenTaskActive() throws InterruptedException { - // Create a task state provider that returns true (task is active) - MockTaskStateProvider stateProvider = new MockTaskStateProvider(true); - queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider, mainEventBus); - - String taskId = "active-task"; - TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId - - // Verify no queue exists initially - assertNull(queueManager.get(taskId)); - - // Create a ChildQueue BEFORE processing the replicated event - // This ensures the ChildQueue exists when MainEventBusProcessor distributes the event - EventQueue childQueue = queueManager.createOrTap(taskId); - assertNotNull(childQueue, "ChildQueue should be created"); - - // Verify MainQueue was created - EventQueue mainQueue = queueManager.get(taskId); - assertNotNull(mainQueue, "MainQueue should exist after createOrTap"); - - // Process a replicated event for an active task - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, eventForTask); - - // Verify the event was enqueued and distributed to our ChildQueue - // Use callback to wait for event processing - EventQueueItem item = dequeueEventWithRetry(childQueue, () -> queueManager.onReplicatedEvent(replicatedEvent)); - assertNotNull(item, "Event should be available in queue"); - Event dequeuedEvent = item.getEvent(); - assertEquals(eventForTask, dequeuedEvent, "Event should be enqueued for active task"); - } - - - @Test - void testReplicatedEventToExistingQueueWhenTaskBecomesInactive() throws InterruptedException { - // Create a task state provider that returns true initially - MockTaskStateProvider stateProvider = new MockTaskStateProvider(true); - queueManager = new ReplicatedQueueManager(new CountingReplicationStrategy(), stateProvider, mainEventBus); - - String taskId = "task-becomes-inactive"; - - // Create queue and enqueue an event - EventQueue queue = queueManager.createOrTap(taskId); - queue.enqueueEvent(getTaskStatusUpdateEventWithNewId(taskId)); - - // Dequeue to clear the queue - try { - queue.dequeueEventItem(100); - } catch (EventQueueClosedException e) { - fail("Queue should not be closed"); - } - - // Now mark task as inactive - stateProvider.setActive(false); - - // Process a replicated event - should be skipped - TaskStatusUpdateEvent newEvent = TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, newEvent); - queueManager.onReplicatedEvent(replicatedEvent); - - // Try to dequeue with a short timeout - should timeout (no new event) - try { - EventQueueItem item = queue.dequeueEventItem(100); - assertNull(item, "No event should be enqueued for inactive task"); - } catch (EventQueueClosedException e) { - fail("Queue should not be closed"); - } - } - - @Test - void testPoisonPillSentViaTransactionAwareEvent() throws InterruptedException { - CountingReplicationStrategy strategy = new CountingReplicationStrategy(); - queueManager = new ReplicatedQueueManager(strategy, new MockTaskStateProvider(true), mainEventBus); - - String taskId = "poison-pill-test"; - EventQueue queue = queueManager.createOrTap(taskId); - TaskStatusUpdateEvent event = createEventForTask(taskId); - - // Enqueue a normal event first and wait for processing - waitForEventProcessing(() -> queue.enqueueEvent(event)); - - // In the new architecture, QueueClosedEvent (poison pill) is sent via CDI events - // when JpaDatabaseTaskStore.save() persists a final task and the transaction commits - // ReplicatedQueueManager.onTaskFinalized() observes AFTER_SUCCESS and sends the poison pill - - // Simulate the CDI event observer being called (what happens in real execution) - // Create a final task for the event - Task finalTask = Task.builder() - .id(taskId) - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - TaskFinalizedEvent taskFinalizedEvent = new TaskFinalizedEvent(taskId, finalTask); - - // Call the observer method directly (simulating CDI event delivery) - queueManager.onTaskFinalized(taskFinalizedEvent); - - // Verify that final Task and QueueClosedEvent were replicated - // strategy.getCallCount() should be 3: testEvent, final Task, then QueueClosedEvent (poison pill) - assertEquals(3, strategy.getCallCount(), "Should have replicated testEvent, final Task, and QueueClosedEvent"); - - // Verify the last event is QueueClosedEvent (poison pill) - Event lastEvent = strategy.getLastEvent(); - assertTrue(lastEvent instanceof QueueClosedEvent, "Last replicated event should be QueueClosedEvent (poison pill)"); - assertEquals(taskId, ((QueueClosedEvent) lastEvent).getTaskId()); - } - - @Test - void testQueueClosedEventJsonSerialization() throws Exception { - // Test that ReplicatedEventQueueItem can serialize/deserialize QueueClosedEvent - String taskId = "closed-event-json-test"; - QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); - ReplicatedEventQueueItem original = new ReplicatedEventQueueItem(taskId, closedEvent); - - // Verify the item is marked as closed event - assertTrue(original.isClosedEvent(), "Should be marked as closed event"); - assertFalse(original.hasEvent(), "Should not have regular event"); - assertFalse(original.hasError(), "Should not have error"); - - // Serialize to JSON - String json = JsonUtil.toJson(original); - assertNotNull(json); - assertTrue(json.contains(taskId), "JSON should contain taskId"); - assertTrue(json.contains("\"closedEvent\":true"), "JSON should contain closedEvent flag"); - - // Deserialize back - ReplicatedEventQueueItem deserialized = JsonUtil.fromJson(json, ReplicatedEventQueueItem.class); - assertNotNull(deserialized); - assertEquals(taskId, deserialized.getTaskId()); - assertTrue(deserialized.isClosedEvent(), "Deserialized should be marked as closed event"); - assertFalse(deserialized.hasEvent(), "Deserialized should not have regular event"); - assertFalse(deserialized.hasError(), "Deserialized should not have error"); - - // Verify getEvent() returns QueueClosedEvent - Event reconstructedEvent = deserialized.getEvent(); - assertNotNull(reconstructedEvent); - assertTrue(reconstructedEvent instanceof QueueClosedEvent, - "getEvent() should return QueueClosedEvent"); - assertEquals(taskId, ((QueueClosedEvent) reconstructedEvent).getTaskId()); - } - - @Test - void testReplicatedQueueClosedEventTerminatesConsumer() throws InterruptedException { - String taskId = "remote-close-test"; - TaskStatusUpdateEvent eventForTask = createEventForTask(taskId); // Use matching taskId - EventQueue queue = queueManager.createOrTap(taskId); - - // Simulate receiving QueueClosedEvent from remote node - QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); - ReplicatedEventQueueItem replicatedClosedEvent = new ReplicatedEventQueueItem(taskId, closedEvent); - - // Dequeue the normal event first (use callback to wait for async processing) - EventQueueItem item1 = dequeueEventWithRetry(queue, () -> queue.enqueueEvent(eventForTask)); - assertNotNull(item1, "First event should be available"); - assertEquals(eventForTask, item1.getEvent()); - - // Next dequeue should get the QueueClosedEvent (use callback to wait for async processing) - EventQueueItem item2 = dequeueEventWithRetry(queue, () -> queueManager.onReplicatedEvent(replicatedClosedEvent)); - assertNotNull(item2, "QueueClosedEvent should be available"); - assertTrue(item2.getEvent() instanceof QueueClosedEvent, - "Second event should be QueueClosedEvent"); - } - - private TaskStatusUpdateEvent getTaskStatusUpdateEventWithNewId(String taskId) { - return TaskStatusUpdateEvent.builder((TaskStatusUpdateEvent) testEvent).taskId(taskId).build(); - } - - - private static class NoOpReplicationStrategy implements ReplicationStrategy { - @Override - public void send(String taskId, Event event) { - // No-op for tests that don't care about replication - } - } - - private static class CountingReplicationStrategy implements ReplicationStrategy { - private final AtomicInteger callCount = new AtomicInteger(0); - private volatile String lastTaskId; - private volatile Event lastEvent; - - @Override - public void send(String taskId, Event event) { - callCount.incrementAndGet(); - this.lastTaskId = taskId; - this.lastEvent = event; - } - - public int getCallCount() { - return callCount.get(); - } - - public String getLastTaskId() { - return lastTaskId; - } - - public Event getLastEvent() { - return lastEvent; - } - } - - - private static class MockTaskStateProvider implements io.a2a.server.tasks.TaskStateProvider { - private volatile boolean active; - - public MockTaskStateProvider(boolean active) { - this.active = active; - } - - @Override - public boolean isTaskActive(String taskId) { - return active; - } - - @Override - public boolean isTaskFinalized(String taskId) { - return !active; // If task is inactive, it's finalized; if active, not finalized - } - - public void setActive(boolean active) { - this.active = active; - } - } - - /** - * Helper method to dequeue an event after waiting for MainEventBusProcessor distribution. - * Uses callback-based waiting instead of polling for deterministic synchronization. - * - * @param queue the queue to dequeue from - * @param enqueueAction the action that enqueues the event (triggers event processing) - * @return the dequeued EventQueueItem, or null if queue is closed - */ - private EventQueueItem dequeueEventWithRetry(EventQueue queue, Runnable enqueueAction) throws InterruptedException { - // Wait for event to be processed and distributed - waitForEventProcessing(enqueueAction); - - // Event is now available, dequeue directly - try { - return queue.dequeueEventItem(100); - } catch (EventQueueClosedException e) { - // Queue closed, return null - return null; - } - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueTestHelper.java b/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueTestHelper.java deleted file mode 100644 index 1b095889b..000000000 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueTestHelper.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.a2a.server.events; - -/** - * Utils to access package private methods in the io.a2a.server.events package - */ -public class EventQueueTestHelper { - public static EventQueue tapQueue(EventQueue queue) { - return queue.tap(); - } -} diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java b/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java deleted file mode 100644 index a91575aaa..000000000 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/server/events/EventQueueUtil.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.a2a.server.events; - -public class EventQueueUtil { - public static void start(MainEventBusProcessor processor) { - processor.start(); - } - - public static void stop(MainEventBusProcessor processor) { - processor.stop(); - } -} diff --git a/extras/queue-manager-replicated/pom.xml b/extras/queue-manager-replicated/pom.xml deleted file mode 100644 index 7503e1340..000000000 --- a/extras/queue-manager-replicated/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-queue-manager-replicated-parent - pom - Java A2A Extras: Replicated Queue Manager Parent - - - core - replication-mp-reactive - tests-single-instance - tests-multi-instance - - - \ No newline at end of file diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml deleted file mode 100644 index e756812f7..000000000 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replication-mp-reactive - Java A2A Extras: Replicated Queue Manager MicroProfile Reactive Messaging - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-jsonrpc-common - ${project.version} - - - io.quarkus - quarkus-messaging - - - io.quarkus - quarkus-smallrye-context-propagation - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - - - org.junit.jupiter - junit-jupiter - test - - - org.mockito - mockito-core - test - - - org.mockito - mockito-junit-jupiter - test - - - - \ No newline at end of file diff --git a/extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java b/extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java deleted file mode 100644 index 6f0ca9876..000000000 --- a/extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.mp_reactive; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.event.Event; -import jakarta.inject.Inject; - -import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.extras.queuemanager.replicated.core.ReplicationStrategy; -import io.a2a.jsonrpc.common.json.JsonUtil; -import org.eclipse.microprofile.reactive.messaging.Channel; -import org.eclipse.microprofile.reactive.messaging.Emitter; -import org.eclipse.microprofile.reactive.messaging.Incoming; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -public class ReactiveMessagingReplicationStrategy implements ReplicationStrategy { - - private static final Logger LOGGER = LoggerFactory.getLogger(ReactiveMessagingReplicationStrategy.class); - - @Inject - @Channel("replicated-events-out") - private Emitter emitter; - - @Inject - private Event cdiEvent; - - @Override - public void send(String taskId, io.a2a.spec.Event event) { - LOGGER.debug("Sending replicated event for task: {}, event: {}", taskId, event); - - try { - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); - String json = JsonUtil.toJson(replicatedEvent); - emitter.send(json); - LOGGER.debug("Successfully sent replicated event for task: {}", taskId); - } catch (Exception e) { - LOGGER.error("Failed to send replicated event for task: {}, event: {}", taskId, event, e); - throw new RuntimeException("Failed to send replicated event", e); - } - } - - @Incoming("replicated-events-in") - public void onReplicatedEvent(String jsonMessage) { - LOGGER.debug("Received replicated event JSON: {}", jsonMessage); - - try { - ReplicatedEventQueueItem replicatedEvent = JsonUtil.fromJson(jsonMessage, ReplicatedEventQueueItem.class); - LOGGER.debug("Deserialized replicated event for task: {}, event: {}", - replicatedEvent.getTaskId(), replicatedEvent.getEvent()); - - // Fire the CDI event directly - cdiEvent.fire(replicatedEvent); - LOGGER.debug("Successfully fired CDI event for task: {}", replicatedEvent.getTaskId()); - } catch (Exception e) { - LOGGER.error("Failed to deserialize replicated event from JSON: {}", jsonMessage, e); - // Don't throw - just log the error and continue processing other messages - // This prevents one bad message from stopping the entire message processing - } - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/replication-mp-reactive/src/main/resources/META-INF/beans.xml b/extras/queue-manager-replicated/replication-mp-reactive/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 6bb944ce2..000000000 --- a/extras/queue-manager-replicated/replication-mp-reactive/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - \ No newline at end of file diff --git a/extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java b/extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java deleted file mode 100644 index d1f48aeb4..000000000 --- a/extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.mp_reactive; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import jakarta.enterprise.event.Event; - -import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.eclipse.microprofile.reactive.messaging.Emitter; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class ReactiveMessagingReplicationStrategyTest { - - @Mock - private Emitter emitter; - - @Mock - private Event cdiEvent; - - @InjectMocks - private ReactiveMessagingReplicationStrategy strategy; - - private StreamingEventKind testEvent; - - @BeforeEach - public void setUp() { - testEvent = TaskStatusUpdateEvent.builder() - .taskId("test-task") - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - } - - private String createValidJsonMessage(String taskId, String contextId) throws Exception { - // Create a proper ReplicatedEventQueueItem JSON with StreamingEventKind - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, event); - return JsonUtil.toJson(replicatedEvent); - } - - @Test - public void testSendCallsEmitter() { - String taskId = "test-task-123"; - - strategy.send(taskId, testEvent); - - // Verify that emitter.send was called (don't care about exact JSON format) - verify(emitter).send(any(String.class)); - } - - @Test - public void testSendPropagatesEmitterExceptions() { - String taskId = "test-task-456"; - RuntimeException emitterException = new RuntimeException("Failed to send replicated event"); - - doThrow(emitterException).when(emitter).send(any(String.class)); - - RuntimeException exception = assertThrows(RuntimeException.class, () -> - strategy.send(taskId, testEvent) - ); - - // The implementation wraps the original exception, so check the cause - assertEquals(emitterException, exception.getCause()); - assertEquals("Failed to send replicated event", exception.getMessage()); - } - - @Test - public void testOnReplicatedEventWithValidJson() throws Exception { - String validJsonMessage = createValidJsonMessage("test-task-101", "test-context"); - - // Should not throw - valid JSON should be handled gracefully - assertDoesNotThrow(() -> strategy.onReplicatedEvent(validJsonMessage)); - - // Note: We test the actual CDI firing in integration tests - // Unit tests here focus on error handling and basic flow - } - - - @Test - public void testOnReplicatedEventHandlesInvalidJson() { - String invalidJsonMessage = "invalid-json"; - - // Should not throw - invalid JSON should be handled gracefully - assertDoesNotThrow(() -> strategy.onReplicatedEvent(invalidJsonMessage)); - - // CDI event should not be fired for invalid JSON - verify(cdiEvent, never()).fire(any(ReplicatedEventQueueItem.class)); - } - - -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/tests-multi-instance/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/pom.xml deleted file mode 100644 index ed8731542..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replicated-tests-multi-instance-parent - pom - Java A2A Extras: Replicated Queue Manager Tests - Multi Instance Parent - - - quarkus-common - quarkus-app-1 - quarkus-app-2 - tests - - - diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/Dockerfile b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/Dockerfile deleted file mode 100644 index 218da8c35..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM mirror.gcr.io/eclipse-temurin:17-jre-jammy - -WORKDIR /app - -# Copy the built Quarkus application -COPY target/quarkus-app/lib/ /app/lib/ -COPY target/quarkus-app/*.jar /app/ -COPY target/quarkus-app/app/ /app/app/ -COPY target/quarkus-app/quarkus/ /app/quarkus/ - -EXPOSE 8081 - -CMD ["java", "-jar", "/app/quarkus-run.jar"] diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml deleted file mode 100644 index c6b46b7a4..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replicated-tests-multi-instance-app-1 - Java A2A Extras: Replicated Queue Manager Tests - Multi Instance App 1 - - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-tests-multi-instance-common - ${project.version} - - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - ${project.version} - - - io.github.a2asdk - a2a-java-queue-manager-replication-mp-reactive - ${project.version} - - - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - - - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - ${project.version} - - - io.quarkus - quarkus-jdbc-postgresql - - - io.quarkus - quarkus-hibernate-orm - - - - - io.quarkus - quarkus-messaging-kafka - - - - - io.quarkus - quarkus-smallrye-health - - - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - - - - - - - diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java deleted file mode 100644 index 4594f10b4..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentCardProducer.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app1; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentCards; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCard; - -@ApplicationScoped -public class MultiInstanceReplicationApp1AgentCardProducer { - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return MultiInstanceReplicationAgentCards.createAgentCard(1, 8081); - } -} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java deleted file mode 100644 index f45a58095..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app1/MultiInstanceReplicationApp1AgentExecutorProducer.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app1; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentExecutor; -import io.a2a.server.agentexecution.AgentExecutor; - -@ApplicationScoped -public class MultiInstanceReplicationApp1AgentExecutorProducer { - - @Produces - public AgentExecutor agentExecutor() { - return new MultiInstanceReplicationAgentExecutor(); - } -} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties deleted file mode 100644 index ea64096cb..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-1/src/main/resources/application.properties +++ /dev/null @@ -1,40 +0,0 @@ -# Application HTTP Port -quarkus.http.port=8081 - -# Configure PostgreSQL database (connection details will be provided by Testcontainers) -quarkus.datasource."a2a-java".db-kind=postgresql -quarkus.datasource."a2a-java".jdbc.url=${DATABASE_URL:jdbc:postgresql://localhost:5432/a2adb} -quarkus.datasource."a2a-java".username=${DATABASE_USER:a2auser} -quarkus.datasource."a2a-java".password=${DATABASE_PASSWORD:a2apass} -quarkus.hibernate-orm."a2a-java".datasource=a2a-java -quarkus.hibernate-orm."a2a-java".database.generation=drop-and-create -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa - -# Configure the outgoing channel (QueueManager -> Kafka) -mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka -mp.messaging.outgoing.replicated-events-out.topic=replicated-events -mp.messaging.outgoing.replicated-events-out.value.serializer=org.apache.kafka.common.serialization.StringSerializer -mp.messaging.outgoing.replicated-events-out.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092} - -# Configure the incoming channel (Kafka -> QueueManager) -mp.messaging.incoming.replicated-events-in.connector=smallrye-kafka -mp.messaging.incoming.replicated-events-in.topic=replicated-events -mp.messaging.incoming.replicated-events-in.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer -mp.messaging.incoming.replicated-events-in.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092} -mp.messaging.incoming.replicated-events-in.group.id=app-1-consumer-group -mp.messaging.incoming.replicated-events-in.auto.offset.reset=earliest - -# Disable DevServices - Testcontainers will manage infrastructure -quarkus.devservices.enabled=false -quarkus.kafka.devservices.enabled=false - -# Reduce timeouts for faster tests -quarkus.messaging.kafka.health.timeout=5s - -# Enable debug logging -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG -quarkus.log.category."io.a2a.client".level=DEBUG diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/Dockerfile b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/Dockerfile deleted file mode 100644 index bc0b294be..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM mirror.gcr.io/eclipse-temurin:17-jre-jammy - -WORKDIR /app - -# Copy the built Quarkus application -COPY target/quarkus-app/lib/ /app/lib/ -COPY target/quarkus-app/*.jar /app/ -COPY target/quarkus-app/app/ /app/app/ -COPY target/quarkus-app/quarkus/ /app/quarkus/ - -EXPOSE 8082 - -CMD ["java", "-jar", "/app/quarkus-run.jar"] diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml deleted file mode 100644 index 39cf7e944..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replicated-tests-multi-instance-app-2 - Java A2A Extras: Replicated Queue Manager Tests - Multi Instance App 2 - - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-tests-multi-instance-common - ${project.version} - - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - ${project.version} - - - io.github.a2asdk - a2a-java-queue-manager-replication-mp-reactive - ${project.version} - - - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - - - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - ${project.version} - - - io.quarkus - quarkus-jdbc-postgresql - - - io.quarkus - quarkus-hibernate-orm - - - - - io.quarkus - quarkus-messaging-kafka - - - - - io.quarkus - quarkus-smallrye-health - - - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - - - - - - - diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java deleted file mode 100644 index 6874601f0..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentCardProducer.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app2; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentCards; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCard; - -@ApplicationScoped -public class MultiInstanceReplicationApp2AgentCardProducer { - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return MultiInstanceReplicationAgentCards.createAgentCard(2, 8082); - } -} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java deleted file mode 100644 index d03388179..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/app2/MultiInstanceReplicationApp2AgentExecutorProducer.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.app2; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import io.a2a.extras.queuemanager.replicated.tests.multiinstance.common.MultiInstanceReplicationAgentExecutor; -import io.a2a.server.agentexecution.AgentExecutor; - -@ApplicationScoped -public class MultiInstanceReplicationApp2AgentExecutorProducer { - - @Produces - public AgentExecutor agentExecutor() { - return new MultiInstanceReplicationAgentExecutor(); - } -} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties b/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties deleted file mode 100644 index d9a495e8f..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-app-2/src/main/resources/application.properties +++ /dev/null @@ -1,40 +0,0 @@ -# Application HTTP Port -quarkus.http.port=8082 - -# Configure PostgreSQL database (connection details will be provided by Testcontainers) -quarkus.datasource."a2a-java".db-kind=postgresql -quarkus.datasource."a2a-java".jdbc.url=${DATABASE_URL:jdbc:postgresql://localhost:5432/a2adb} -quarkus.datasource."a2a-java".username=${DATABASE_USER:a2auser} -quarkus.datasource."a2a-java".password=${DATABASE_PASSWORD:a2apass} -quarkus.hibernate-orm."a2a-java".datasource=a2a-java -quarkus.hibernate-orm."a2a-java".database.generation=drop-and-create -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa - -# Configure the outgoing channel (QueueManager -> Kafka) -mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka -mp.messaging.outgoing.replicated-events-out.topic=replicated-events -mp.messaging.outgoing.replicated-events-out.value.serializer=org.apache.kafka.common.serialization.StringSerializer -mp.messaging.outgoing.replicated-events-out.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092} - -# Configure the incoming channel (Kafka -> QueueManager) -mp.messaging.incoming.replicated-events-in.connector=smallrye-kafka -mp.messaging.incoming.replicated-events-in.topic=replicated-events -mp.messaging.incoming.replicated-events-in.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer -mp.messaging.incoming.replicated-events-in.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092} -mp.messaging.incoming.replicated-events-in.group.id=app-2-consumer-group -mp.messaging.incoming.replicated-events-in.auto.offset.reset=earliest - -# Disable DevServices - Testcontainers will manage infrastructure -quarkus.devservices.enabled=false -quarkus.kafka.devservices.enabled=false - -# Reduce timeouts for faster tests -quarkus.messaging.kafka.health.timeout=5s - -# Enable debug logging -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.extras.taskstore.database.jpa".level=DEBUG -quarkus.log.category."io.a2a.client".level=DEBUG diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml deleted file mode 100644 index c1b6d6a6a..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replicated-tests-multi-instance-common - Java A2A Extras: Replicated Queue Manager Tests - Multi Instance Common - - - - - io.github.a2asdk - a2a-java-sdk-spec - - - - - io.github.a2asdk - a2a-java-sdk-server-common - - - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java deleted file mode 100644 index 4d1133ad9..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentCards.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.common; - - -import java.util.Collections; -import java.util.List; - -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; - -/** - * Shared AgentCard factory for multi-instance replication tests. - */ -public final class MultiInstanceReplicationAgentCards { - - private MultiInstanceReplicationAgentCards() { - } - - /** - * Creates an AgentCard for a test instance. - * - * @param instanceNumber the instance number (e.g., 1, 2) - * @param port the port number (e.g., 8081, 8082) - * @return the configured AgentCard - */ - public static AgentCard createAgentCard(int instanceNumber, int port) { - String url = "http://localhost:" + port; - - return AgentCard.builder() - .name("Multi-Instance Test Agent " + instanceNumber) - .description("Test agent for multi-instance replication testing - Instance " + instanceNumber) - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), url))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(AgentSkill.builder() - .id("replication_test") - .name("Replication Test") - .description("Fire-and-forget agent for testing replication") - .tags(Collections.singletonList("test")) - .build())) - .build(); - } -} diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java deleted file mode 100644 index d51ef8f32..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance.common; - -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TextPart; - -/** - * Shared test agent executor for multi-instance replication tests. - * - * Behavior: - * 1. Creates task in SUBMITTED state on first message - * 2. Adds messages as artifacts on subsequent messages - * 3. Completes task when message contains "close" - */ -public class MultiInstanceReplicationAgentExecutor implements AgentExecutor { - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - Task task = context.getTask(); - - // Check if message contains "close" signal - boolean shouldClose = context.getMessage().parts().stream() - .anyMatch(part -> part instanceof TextPart tp && - tp.text() != null && - tp.text().toLowerCase().contains("close")); - - if (shouldClose) { - // Close the task - agentEmitter.complete(); - } else if (task == null) { - // First message - create task in SUBMITTED state - agentEmitter.submit(); - } else { - // Subsequent messages - add as artifact - agentEmitter.addArtifact(context.getMessage().parts()); - } - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - agentEmitter.cancel(); - } -} diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml b/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml deleted file mode 100644 index f3c2491e8..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-queue-manager-replicated-tests-multi-instance-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replicated-tests-multi-instance-tests - Java A2A Extras: Replicated Queue Manager Tests - Multi Instance Tests - - - - - io.github.a2asdk - a2a-java-sdk-client - test - - - io.github.a2asdk - a2a-java-sdk-transport-jsonrpc - test - - - - - io.quarkus - quarkus-junit5 - test - - - - - org.testcontainers - testcontainers - test - - - org.testcontainers - junit-jupiter - test - - - org.testcontainers - kafka - test - - - org.testcontainers - postgresql - test - - - - - org.awaitility - awaitility - test - - - - - org.slf4j - slf4j-api - test - - - ch.qos.logback - logback-classic - test - - - - - - - maven-surefire-plugin - - - - org.jboss.logmanager.LogManager - - - - - - diff --git a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java b/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java deleted file mode 100644 index 44b8d88b8..000000000 --- a/extras/queue-manager-replicated/tests-multi-instance/tests/src/test/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/MultiInstanceReplicationTest.java +++ /dev/null @@ -1,529 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests.multiinstance; - -import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.File; -import java.io.IOException; -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TransportProtocol; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.KafkaContainer; -import org.testcontainers.containers.Network; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.containers.wait.strategy.Wait; -import org.testcontainers.images.builder.ImageFromDockerfile; -import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.utility.DockerImageName; - -/** - * Multi-instance replication test that validates event queue replication - * between two running Quarkus instances using Testcontainers. - * - * Test Architecture: - * - Shared KafkaContainer for event replication - * - Shared PostgreSQLContainer for task persistence - * - Two Quarkus application containers (app1 on 8081, app2 on 8082) - * - A2A Client instances to interact with both applications - */ -@Testcontainers -public class MultiInstanceReplicationTest { - - private static final String KAFKA_IMAGE = "confluentinc/cp-kafka:7.6.1"; - private static final String POSTGRES_IMAGE = "postgres:16-alpine"; - - private static Network network; - private static KafkaContainer kafka; - private static PostgreSQLContainer postgres; - private static GenericContainer app1; - private static GenericContainer app2; - - private static String app1Url; - private static String app2Url; - private static AgentCard app1Card; - private static AgentCard app2Card; - - private Client client1; - private Client client2; - - @BeforeAll - public static void setup() { - // Create a shared network for all containers - network = Network.newNetwork(); - - // Start Kafka container - kafka = new KafkaContainer(DockerImageName.parse(KAFKA_IMAGE)) - .withNetwork(network) - .withNetworkAliases("kafka") - .withEnv("KAFKA_AUTO_CREATE_TOPICS_ENABLE", "true"); - kafka.start(); - - // Start PostgreSQL container - postgres = new PostgreSQLContainer<>(DockerImageName.parse(POSTGRES_IMAGE)) - .withNetwork(network) - .withNetworkAliases("postgres") - .withDatabaseName("a2adb") - .withUsername("a2auser") - .withPassword("a2apass"); - postgres.start(); - - // Get Kafka bootstrap servers for app configuration - // Kafka is accessible within the Docker network as "kafka:9092" - String kafkaBootstrapServers = "kafka:9092"; - - // PostgreSQL connection details for apps (using network alias) - String dbUrl = "jdbc:postgresql://postgres:5432/a2adb"; - String dbUser = "a2auser"; - String dbPassword = "a2apass"; - - // Build and start Quarkus app1 container - File app1Dir = new File("../quarkus-app-1").getAbsoluteFile(); - app1 = new GenericContainer<>( - new ImageFromDockerfile() - .withFileFromPath(".", app1Dir.toPath())) - .withNetwork(network) - .withNetworkAliases("app1") - .withEnv("KAFKA_BOOTSTRAP_SERVERS", kafkaBootstrapServers) - .withEnv("DATABASE_URL", dbUrl) - .withEnv("DATABASE_USER", dbUser) - .withEnv("DATABASE_PASSWORD", dbPassword) - .withExposedPorts(8081) - .waitingFor(Wait.forHttp("/q/health/ready") - .forPort(8081) - .withStartupTimeout(Duration.ofMinutes(2))); - app1.start(); - - // Build and start Quarkus app2 container - File app2Dir = new File("../quarkus-app-2").getAbsoluteFile(); - app2 = new GenericContainer<>( - new ImageFromDockerfile() - .withFileFromPath(".", app2Dir.toPath())) - .withNetwork(network) - .withNetworkAliases("app2") - .withEnv("KAFKA_BOOTSTRAP_SERVERS", kafkaBootstrapServers) - .withEnv("DATABASE_URL", dbUrl) - .withEnv("DATABASE_USER", dbUser) - .withEnv("DATABASE_PASSWORD", dbPassword) - .withExposedPorts(8082) - .waitingFor(Wait.forHttp("/q/health/ready") - .forPort(8082) - .withStartupTimeout(Duration.ofMinutes(2))); - app2.start(); - - // Store URLs for creating clients - app1Url = "http://localhost:" + app1.getMappedPort(8081); - app2Url = "http://localhost:" + app2.getMappedPort(8082); - - // Get AgentCards from both apps and patch URLs to use mapped ports - try { - AgentCard originalApp1Card = A2A.getAgentCard(app1Url); - AgentCard originalApp2Card = A2A.getAgentCard(app2Url); - - // Rebuild AgentCards with correct URLs (mapped ports, not container ports) - app1Card = AgentCard.builder(originalApp1Card) - .supportedInterfaces(Collections.singletonList( - new AgentInterface(TransportProtocol.JSONRPC.asString(), app1Url) - )) - .build(); - - app2Card = AgentCard.builder(originalApp2Card) - .supportedInterfaces(Collections.singletonList( - new AgentInterface(TransportProtocol.JSONRPC.asString(), app2Url) - )) - .build(); - } catch (Exception e) { - System.err.println("=== Failed to get AgentCards ==="); - System.err.println("App1 logs:"); - System.err.println(app1.getLogs()); - System.err.println("\nApp2 logs:"); - System.err.println(app2.getLogs()); - throw new RuntimeException("Failed to get AgentCards", e); - } - } - - @AfterAll - public static void teardown() { - if (app2 != null) { - app2.stop(); - } - if (app1 != null) { - app1.stop(); - } - if (postgres != null) { - postgres.stop(); - } - if (kafka != null) { - kafka.stop(); - } - if (network != null) { - network.close(); - } - } - - @AfterEach - public void cleanupClients() throws Exception { - if (client1 != null) { - client1.close(); - client1 = null; - } - if (client2 != null) { - client2.close(); - client2 = null; - } - } - - // Helper methods for creating A2A clients - - private Client createClient(AgentCard agentCard) throws A2AClientException { - ClientConfig config = ClientConfig.builder() - .setStreaming(true) - .build(); - - return Client.builder(agentCard) - .clientConfig(config) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) - .build(); - } - - private Client getClient1() throws A2AClientException { - if (client1 == null) { - client1 = createClient(app1Card); - } - return client1; - } - - private Client getClient2() throws A2AClientException { - if (client2 == null) { - client2 = createClient(app2Card); - } - return client2; - } - - @Test - public void testInfrastructureStartup() { - // Verify that all containers started successfully - assertTrue(kafka.isRunning(), "Kafka container should be running"); - assertTrue(postgres.isRunning(), "PostgreSQL container should be running"); - assertTrue(app1.isRunning(), "App1 container should be running"); - assertTrue(app2.isRunning(), "App2 container should be running"); - - assertNotNull(kafka.getBootstrapServers()); - assertNotNull(postgres.getJdbcUrl()); - assertNotNull(app1.getMappedPort(8081)); - assertNotNull(app2.getMappedPort(8082)); - } - - /** - * Main multi-instance replication test following architect's guidance: - * 1. Send initial message on app1 (creates task in non-final state) - * 2. Subscribe to that task from both app1 and app2 - * 3. Send message on app1, verify both subscribers receive it - * 4. Send message on app2, verify both subscribers receive it - * 5. Send final message to transition task to COMPLETED - * 6. Verify final state reflected on both subscribers - */ - @Test - public void testMultiInstanceEventReplication() throws Exception { - final String taskId = "replication-test-task-" + System.currentTimeMillis(); - final String contextId = "replication-test-context"; - - Throwable testFailure = null; - try { - // Step 1: Send initial message NON-streaming to create task - Message initialMessage = Message.builder(A2A.toUserMessage("Initial test message")) - .taskId(taskId) - .contextId(contextId) - .build(); - - // Use NON-streaming client to create the task - // Note: app1Card has the correct URL from Testcontainers setup - Client nonStreamingClient = Client.builder(app1Card) - .clientConfig(ClientConfig.builder().setStreaming(false).build()) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) - .build(); - - Task createdTask = null; - try { - nonStreamingClient.sendMessage(initialMessage, null); - - // Retrieve the task to verify it was created - createdTask = nonStreamingClient.getTask(new TaskQueryParams(taskId), null); - assertNotNull(createdTask, "Task should be created"); - - // Task should be in a non-final state (SUBMITTED or WORKING are both valid) - TaskState state = createdTask.status().state(); - assertTrue(state == TaskState.TASK_STATE_SUBMITTED || state == TaskState.TASK_STATE_WORKING, - "Task should be in SUBMITTED or WORKING state, but was: " + state); - nonStreamingClient.close(); - } catch (Exception e) { - System.err.println("\n=== FAILED TO CREATE TASK ==="); - System.err.println("Error: " + e.getMessage()); - System.err.println("\n=== APP1 CONTAINER LOGS ==="); - System.err.println(app1.getLogs()); - - System.err.println("\n=== APP2 CONTAINER LOGS ==="); - System.err.println(app2.getLogs()); - - throw e; - } - - // Step 2: Subscribe from both app1 and app2 with proper latches - - // We need to wait for at least 3 new events after resubscription: - // 1. TaskArtifactUpdateEvent (message from app1) - // 2. TaskArtifactUpdateEvent (message from app2) - // 3. TaskStatusUpdateEvent(COMPLETED) (close message) - // Note: may also receive initial TaskEvent/TaskUpdateEvent when resubscribing - AtomicInteger app1EventCount = new AtomicInteger(0); - AtomicInteger app2EventCount = new AtomicInteger(0); - - // Track events received - CopyOnWriteArrayList app1Events = new CopyOnWriteArrayList<>(); - CopyOnWriteArrayList app2Events = new CopyOnWriteArrayList<>(); - - AtomicReference app1Error = new AtomicReference<>(); - AtomicReference app2Error = new AtomicReference<>(); - AtomicBoolean app1ReceivedInitialTask = new AtomicBoolean(false); - AtomicBoolean app2ReceivedInitialTask = new AtomicBoolean(false); - - // App1 subscriber - BiConsumer app1Subscriber = (event, card) -> { - String eventDetail = event.getClass().getSimpleName(); - if (event instanceof io.a2a.client.TaskUpdateEvent tue) { - eventDetail += " [" + tue.getUpdateEvent().getClass().getSimpleName(); - if (tue.getUpdateEvent() instanceof io.a2a.spec.TaskStatusUpdateEvent statusEvent) { - eventDetail += ", state=" + (statusEvent.status() != null ? statusEvent.status().state() : "null"); - } - eventDetail += "]"; - } else if (event instanceof io.a2a.client.TaskEvent te) { - eventDetail += " [state=" + (te.getTask().status() != null ? te.getTask().status().state() : "null") + "]"; - } - System.out.println("APP1 received event: " + eventDetail); - - // Per A2A spec 3.1.6: Handle initial TaskEvent on subscribe - if (!app1ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { - app1ReceivedInitialTask.set(true); - System.out.println("APP1 filtered initial TaskEvent"); - // Don't count initial TaskEvent toward expected artifact/status events - return; - } - app1Events.add(event); - int count = app1EventCount.incrementAndGet(); - System.out.println("APP1 event count now: " + count + ", event: " + eventDetail); - }; - - Consumer app1ErrorHandler = error -> { - if (!isStreamClosedError(error)) { - app1Error.set(error); - } - }; - - // App2 subscriber - BiConsumer app2Subscriber = (event, card) -> { - String eventDetail = event.getClass().getSimpleName(); - if (event instanceof io.a2a.client.TaskUpdateEvent tue) { - eventDetail += " [" + tue.getUpdateEvent().getClass().getSimpleName(); - if (tue.getUpdateEvent() instanceof io.a2a.spec.TaskStatusUpdateEvent statusEvent) { - eventDetail += ", state=" + (statusEvent.status() != null ? statusEvent.status().state() : "null"); - } - eventDetail += "]"; - } else if (event instanceof io.a2a.client.TaskEvent te) { - eventDetail += " [state=" + (te.getTask().status() != null ? te.getTask().status().state() : "null") + "]"; - } - System.out.println("APP2 received event: " + eventDetail); - - // Per A2A spec 3.1.6: Handle initial TaskEvent on subscribe - if (!app2ReceivedInitialTask.get() && event instanceof io.a2a.client.TaskEvent) { - app2ReceivedInitialTask.set(true); - System.out.println("APP2 filtered initial TaskEvent"); - // Don't count initial TaskEvent toward expected artifact/status events - return; - } - app2Events.add(event); - int count = app2EventCount.incrementAndGet(); - System.out.println("APP2 event count now: " + count + ", event: " + eventDetail); - }; - - Consumer app2ErrorHandler = error -> { - if (!isStreamClosedError(error)) { - app2Error.set(error); - } - }; - - // Start subscriptions (subscribe returns void) - getClient1().subscribeToTask(new TaskIdParams(taskId), List.of(app1Subscriber), app1ErrorHandler); - getClient2().subscribeToTask(new TaskIdParams(taskId), List.of(app2Subscriber), app2ErrorHandler); - - // Wait for subscriptions to be established - at least one event should arrive on each - await() - .atMost(Duration.ofSeconds(10)) - .pollInterval(Duration.ofMillis(500)) - .until(() -> app1EventCount.get() >= 1 && app2EventCount.get() >= 1); - - // Step 3: Send message on app1 (should generate TaskArtifactUpdateEvent) - int app1BeforeMsg1 = app1EventCount.get(); - int app2BeforeMsg1 = app2EventCount.get(); - - Message messageFromApp1 = Message.builder(A2A.toUserMessage("Message from app1")) - .taskId(taskId) - .contextId(contextId) - .build(); - getClient1().sendMessage(messageFromApp1, List.of(), null); - - // Wait for both subscribers to receive the replicated event - await() - .atMost(Duration.ofSeconds(10)) - .pollInterval(Duration.ofMillis(500)) - .until(() -> app1EventCount.get() > app1BeforeMsg1 && - app2EventCount.get() > app2BeforeMsg1); - - // Step 4: Send message on app2 (should generate TaskArtifactUpdateEvent) - int app1BeforeMsg2 = app1EventCount.get(); - int app2BeforeMsg2 = app2EventCount.get(); - - Message messageFromApp2 = Message.builder(A2A.toUserMessage("Message from app2")) - .taskId(taskId) - .contextId(contextId) - .build(); - getClient2().sendMessage(messageFromApp2, List.of(), null); - - // Wait for both subscribers to receive the replicated event - await() - .atMost(Duration.ofSeconds(10)) - .pollInterval(Duration.ofMillis(500)) - .until(() -> app1EventCount.get() > app1BeforeMsg2 && - app2EventCount.get() > app2BeforeMsg2); - - // Step 5: Send close message (should generate TaskStatusUpdateEvent with COMPLETED) - int app1BeforeClose = app1EventCount.get(); - int app2BeforeClose = app2EventCount.get(); - - Message closeMessage = Message.builder(A2A.toUserMessage("close")) - .taskId(taskId) - .contextId(contextId) - .build(); - getClient1().sendMessage(closeMessage, List.of(), null); - - // Wait for both subscribers to receive the completion event - await() - .atMost(Duration.ofSeconds(10)) - .pollInterval(Duration.ofMillis(500)) - .until(() -> app1EventCount.get() > app1BeforeClose && - app2EventCount.get() > app2BeforeClose); - - - // Verify we got at least 3 new events after initial subscription (artifact1, artifact2, completed) - assertTrue(app1Events.size() >= 3, - "App1 should receive at least 3 events (got " + app1Events.size() + ")"); - assertTrue(app2Events.size() >= 3, - "App2 should receive at least 3 events (got " + app2Events.size() + ")"); - - // Verify no errors - if (app1Error.get() != null) { - throw new AssertionError("App1 subscriber error", app1Error.get()); - } - if (app2Error.get() != null) { - throw new AssertionError("App2 subscriber error", app2Error.get()); - } - - // Verify both received at least 3 events (could be more due to initial state events) - assertTrue(app1Events.size() >= 3, "App1 should receive at least 3 events, got: " + app1Events.size()); - assertTrue(app2Events.size() >= 3, "App2 should receive at least 3 events, got: " + app2Events.size()); - } catch (Throwable t) { - testFailure = t; - throw t; - } finally { - // Output container logs if test failed - if (testFailure != null) { - System.err.println("\n========================================"); - System.err.println("TEST FAILED - Dumping container logs"); - System.err.println("========================================\n"); - - dumpContainerLogs("KAFKA", kafka, 100); - dumpContainerLogs("APP1", app1, 200); - dumpContainerLogs("APP2", app2, 200); - - System.err.println("\n========================================"); - System.err.println("END OF CONTAINER LOGS"); - System.err.println("========================================\n"); - } - } - } - - /** - * Dumps the last N lines of logs from a container to stderr. - */ - private void dumpContainerLogs(String containerName, org.testcontainers.containers.ContainerState container, int lastLines) { - System.err.println("\n--- " + containerName + " LOGS (last " + lastLines + " lines) ---"); - try { - String logs = container.getLogs(); - String[] lines = logs.split("\n"); - int start = Math.max(0, lines.length - lastLines); - for (int i = start; i < lines.length; i++) { - System.err.println(lines[i]); - } - } catch (Exception e) { - System.err.println("Failed to retrieve " + containerName + " logs: " + e.getMessage()); - } - } - - /** - * Checks if the error is a normal stream closure error that should be ignored. - * HTTP/2 stream cancellation and closure are expected during cleanup. - */ - private boolean isStreamClosedError(Throwable error) { - if (error == null) { - return false; - } - - // Check for IOException which includes stream cancellation - if (error instanceof IOException) { - String message = error.getMessage(); - if (message != null) { - // Filter out normal stream closure/cancellation errors - if (message.contains("Stream closed") || - message.contains("Stream") && message.contains("cancelled") || - message.contains("EOF reached") || - message.contains("CANCEL")) { - return true; - } - } - } - - // Check cause recursively - Throwable cause = error.getCause(); - if (cause != null && cause != error) { - return isStreamClosedError(cause); - } - - return false; - } -} diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml deleted file mode 100644 index 93c6d88e5..000000000 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - 4.0.0 - - io.github.a2asdk - a2a-java-queue-manager-replicated-parent - 1.0.0.Alpha4-SNAPSHOT - ../pom.xml - - - a2a-java-queue-manager-replicated-tests-single-instance - Java A2A Extras: Replicated Queue Manager Tests - Single Instance - - - - - io.github.a2asdk - a2a-java-queue-manager-replicated-core - ${project.version} - - - io.github.a2asdk - a2a-java-queue-manager-replication-mp-reactive - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-jsonrpc-common - ${project.version} - - - - - io.github.a2asdk - a2a-java-sdk-reference-jsonrpc - - - - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - ${project.version} - test - - - io.quarkus - quarkus-jdbc-h2 - test - - - io.quarkus - quarkus-hibernate-orm - test - - - - - io.github.a2asdk - a2a-java-sdk-client - test - - - io.github.a2asdk - a2a-java-sdk-transport-jsonrpc - test - - - - - io.quarkus - quarkus-junit5 - test - - - io.quarkus - quarkus-messaging-kafka - test - - - org.awaitility - awaitility - test - - - - - - - java24-exclude-vertx-incompatible-tests - - [24,) - - - - - maven-surefire-plugin - - --add-opens java.base/java.lang=ALL-UNNAMED - - - **/KafkaReplicationIntegrationTest.java - - - - - - - - - - - - io.quarkus - quarkus-maven-plugin - - - - build - - - - - - - \ No newline at end of file diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java deleted file mode 100644 index 4add5540b..000000000 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java +++ /dev/null @@ -1,507 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import jakarta.inject.Inject; - -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.QueueClosedEvent; -import io.a2a.server.events.QueueManager; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.quarkus.test.junit.QuarkusTest; -import org.eclipse.microprofile.reactive.messaging.Channel; -import org.eclipse.microprofile.reactive.messaging.Emitter; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Integration test for Kafka replication functionality. - * Tests the full A2A message flow with Kafka replication verification. - */ -@QuarkusTest -public class KafkaReplicationIntegrationTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(KafkaReplicationIntegrationTest.class); - - @Inject - @PublicAgentCard - AgentCard agentCard; - - @Inject - TestKafkaEventConsumer testConsumer; - - @Inject - @Channel("replicated-events-out") - Emitter testEmitter; - - @Inject - QueueManager queueManager; - - private Client streamingClient; - private Client nonStreamingClient; - private Client pollingClient; - - @BeforeEach - public void setup() throws A2AClientException { - // Create non-streaming client for initial task creation - ClientConfig nonStreamingConfig = new ClientConfig.Builder() - .setStreaming(false) - .build(); - - nonStreamingClient = Client.builder(agentCard) - .clientConfig(nonStreamingConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - - // Create streaming client for resubscription - ClientConfig streamingConfig = new ClientConfig.Builder() - .setStreaming(true) - .build(); - - streamingClient = Client.builder(agentCard) - .clientConfig(streamingConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - - // Create polling client for non-blocking operations - ClientConfig pollingConfig = new ClientConfig.Builder() - .setStreaming(false) - .setPolling(true) - .build(); - - pollingClient = Client.builder(agentCard) - .clientConfig(pollingConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - } - - @AfterEach - public void tearDown() throws Exception { - // Close all clients to release resources and prevent connection leaks - if (nonStreamingClient != null) { - nonStreamingClient.close(); - } - if (streamingClient != null) { - streamingClient.close(); - } - if (pollingClient != null) { - pollingClient.close(); - } - } - - @Test - public void testA2AMessageReplicatedToKafka() throws Exception { - String taskId = "kafka-replication-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - - // Clear any previous events - testConsumer.clear(); - - // Send A2A message that should trigger events and replication - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("create"))) - .taskId(taskId) - .messageId("test-msg-" + System.currentTimeMillis()) - .contextId(contextId) - .build(); - - CountDownLatch a2aLatch = new CountDownLatch(1); - AtomicReference createdTask = new AtomicReference<>(); - AtomicBoolean a2aError = new AtomicBoolean(false); - - // Send message and verify A2A processing works - nonStreamingClient.sendMessage(message, List.of((ClientEvent event, AgentCard card) -> { - if (event instanceof TaskEvent taskEvent) { - createdTask.set(taskEvent.getTask()); - a2aLatch.countDown(); - } - }), (Throwable error) -> { - a2aError.set(true); - a2aLatch.countDown(); - }); - - // Wait for A2A processing to complete - assertTrue(a2aLatch.await(15, TimeUnit.SECONDS), "A2A message processing timed out"); - assertFalse(a2aError.get(), "A2A processing failed"); - - Task task = createdTask.get(); - assertNotNull(task, "Task should be created"); - assertEquals(taskId, task.id()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, task.status().state()); - - // Wait for the event to be replicated to Kafka - ReplicatedEventQueueItem replicatedEvent = testConsumer.waitForEvent(taskId, 30); - assertNotNull(replicatedEvent, "Event should be replicated to Kafka within 30 seconds"); - - // Verify the replicated event content - assertEquals(taskId, replicatedEvent.getTaskId()); - io.a2a.spec.Event receivedEvent = replicatedEvent.getEvent(); - assertNotNull(receivedEvent); - - // The event should now maintain its proper type through Kafka serialization - // This verifies that our polymorphic serialization is working correctly - assertInstanceOf(TaskStatusUpdateEvent.class, receivedEvent, "Event should maintain TaskStatusUpdateEvent type after Kafka round-trip"); - TaskStatusUpdateEvent statusUpdateEvent = (TaskStatusUpdateEvent) receivedEvent; - - // Verify the event data is consistent with the task returned from the client - assertEquals(taskId, statusUpdateEvent.taskId(), "Event task ID should match original task ID"); - assertEquals(contextId, statusUpdateEvent.contextId(), "Event context ID should match original context ID"); - assertEquals(TaskState.TASK_STATE_SUBMITTED, statusUpdateEvent.status().state(), "Event should show SUBMITTED state"); - assertFalse(statusUpdateEvent.isFinal(), "Event should show final:false"); - assertEquals(TaskStatusUpdateEvent.STREAMING_EVENT_ID, statusUpdateEvent.kind(), "Event should indicate status-update type"); - } - - @Test - public void testKafkaEventReceivedByA2AServer() throws Exception { - String taskId = "kafka-to-a2a-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - - // Clear any previous events - testConsumer.clear(); - - // First create a task in the A2A system using non-streaming client - Message createMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("create"))) - .taskId(taskId) - .messageId("create-msg-" + System.currentTimeMillis()) - .contextId(contextId) - .build(); - - CountDownLatch createLatch = new CountDownLatch(1); - AtomicReference createdTask = new AtomicReference<>(); - - nonStreamingClient.sendMessage(createMessage, List.of((ClientEvent event, AgentCard card) -> { - if (event instanceof TaskEvent taskEvent) { - createdTask.set(taskEvent.getTask()); - createLatch.countDown(); - } - }), (Throwable error) -> { - createLatch.countDown(); - }); - - assertTrue(createLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); - Task initialTask = createdTask.get(); - assertNotNull(initialTask, "Task should be created"); - assertEquals(TaskState.TASK_STATE_SUBMITTED, initialTask.status().state(), "Initial task should be in SUBMITTED state"); - - // Add a small delay to ensure the task is fully processed before resubscription - Thread.sleep(1000); - - // Set up resubscription to listen for task updates using streaming client - CountDownLatch subscribeLatch = new CountDownLatch(1); - AtomicReference receivedCompletedEvent = new AtomicReference<>(); - AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); - AtomicReference errorRef = new AtomicReference<>(); - AtomicBoolean receivedInitialTask = new AtomicBoolean(false); - - // Create consumer to handle subscribed events - BiConsumer consumer = (event, agentCard) -> { - // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent - if (!receivedInitialTask.get()) { - if (event instanceof TaskEvent) { - receivedInitialTask.set(true); - return; - } else { - throw new AssertionError("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); - } - } - - // Process subsequent events - if (event instanceof TaskUpdateEvent taskUpdateEvent) { - if (taskUpdateEvent.getUpdateEvent() instanceof TaskStatusUpdateEvent statusEvent) { - if (statusEvent.status().state() == TaskState.TASK_STATE_COMPLETED) { - receivedCompletedEvent.set(statusEvent); - subscribeLatch.countDown(); - } - } else { - wasUnexpectedEvent.set(true); - } - } else { - wasUnexpectedEvent.set(true); - } - }; - - // Create error handler - filter out benign stream closed errors. - // HTTP/2 streams are cancelled during normal cleanup when subscriptions end, - // which is expected behavior and not an actual error condition. - Consumer errorHandler = error -> { - if (!isStreamClosedError(error)) { - errorRef.set(error); - } - subscribeLatch.countDown(); - }; - - // Subscribe to the task to listen for updates - streamingClient.subscribeToTask(new TaskIdParams(taskId), List.of(consumer), errorHandler); - - // Now manually send a TaskStatusUpdateEvent to Kafka using reactive messaging - TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - ReplicatedEventQueueItem replicatedEvent = new ReplicatedEventQueueItem(taskId, statusEvent); - String eventJson = JsonUtil.toJson(replicatedEvent); - - // Send to Kafka using reactive messaging - testEmitter.send(eventJson); - - // Wait for the replicated event to be received via streaming resubscription - // This tests the full round-trip: Manual Kafka Event -> A2A System -> Streaming Client - assertTrue(subscribeLatch.await(15, TimeUnit.SECONDS), "Should receive COMPLETED event via resubscription"); - - // Verify no unexpected events or errors - assertFalse(wasUnexpectedEvent.get(), "Should not receive unexpected events"); - assertNull(errorRef.get(), "Should not receive errors during resubscription"); - - // Verify the received event - TaskStatusUpdateEvent completedEvent = receivedCompletedEvent.get(); - assertNotNull(completedEvent, "Should have received a TaskStatusUpdateEvent"); - assertEquals(TaskState.TASK_STATE_COMPLETED, completedEvent.status().state(), "Event should show COMPLETED state"); - assertTrue(completedEvent.isFinal(), "Event should be marked as final"); - assertEquals(taskId, completedEvent.taskId(), "Event should have correct task ID"); - assertEquals(contextId, completedEvent.contextId(), "Event should have correct context ID"); - - // Note: We do NOT verify TaskStore state here because replicated events intentionally - // skip TaskStore updates to avoid duplicates. The TaskStore is updated on the originating - // node that produced the event. This test verifies the replication flow: - // Kafka -> EventQueue -> Streaming Clients, which is working correctly. - } - - @Test - public void testQueueClosedEventTerminatesRemoteSubscribers() throws Exception { - String taskId = "queue-closed-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - - // Clear any previous events - testConsumer.clear(); - - // Use polling (non-blocking) client with "working" command - // This creates task in WORKING state (non-final) and keeps queue alive - Message workingMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("working"))) - .taskId(taskId) - .messageId("working-msg-" + System.currentTimeMillis()) - .contextId(contextId) - .build(); - - CountDownLatch workingLatch = new CountDownLatch(1); - AtomicReference taskIdRef = new AtomicReference<>(); - - pollingClient.sendMessage(workingMessage, List.of((ClientEvent event, AgentCard card) -> { - if (event instanceof TaskEvent taskEvent) { - taskIdRef.set(taskEvent.getTask().id()); - workingLatch.countDown(); - } else if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent status) { - if (status.status().state() == TaskState.TASK_STATE_WORKING) { - taskIdRef.set(status.taskId()); - workingLatch.countDown(); - } - } - }), (Throwable error) -> { - workingLatch.countDown(); - }); - - assertTrue(workingLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); - String createdTaskId = taskIdRef.get(); - assertNotNull(createdTaskId, "Task should be created"); - assertEquals(taskId, createdTaskId); - - // Set up streaming resubscription to listen for the QueueClosedEvent - CountDownLatch streamCompletedLatch = new CountDownLatch(1); - AtomicBoolean streamCompleted = new AtomicBoolean(false); - AtomicBoolean streamErrored = new AtomicBoolean(false); - AtomicReference errorRef = new AtomicReference<>(); - - // Create consumer - we expect the stream to complete when QueueClosedEvent arrives - BiConsumer consumer = (event, agentCard) -> { - // We might receive some events before the stream completes, that's fine - // The important thing is that the stream eventually completes - }; - - // Create error handler that captures completion - Consumer errorHandler = error -> { - if (error == null) { - // null error means stream completed normally - streamCompleted.set(true); - } else { - streamErrored.set(true); - errorRef.set(error); - } - streamCompletedLatch.countDown(); - }; - - // Subscribe to the task - this creates a streaming subscription - streamingClient.subscribeToTask(new TaskIdParams(taskId), List.of(consumer), errorHandler); - - // Wait for the EventConsumer to start polling (replaces unreliable Thread.sleep) - // This ensures the consumer is ready to receive the QueueClosedEvent - EventQueue queue = queueManager.get(taskId); - assertNotNull(queue, "Queue should exist for task " + taskId); - queueManager.awaitQueuePollerStart(queue); - - // Now manually send a QueueClosedEvent to Kafka to simulate queue closure on another node - QueueClosedEvent closedEvent = new QueueClosedEvent(taskId); - ReplicatedEventQueueItem replicatedClosedEvent = new ReplicatedEventQueueItem(taskId, closedEvent); - String eventJson = JsonUtil.toJson(replicatedClosedEvent); - - // Send to Kafka using reactive messaging - testEmitter.send(eventJson); - - // Wait for the stream to complete - should happen when QueueClosedEvent is received - // Allow extra time for Kafka message processing and CDI event propagation - assertTrue(streamCompletedLatch.await(30, TimeUnit.SECONDS), - "Streaming subscription should complete when QueueClosedEvent is received"); - - // Verify the stream completed normally (not with an error) - if (!streamCompleted.get()) { - LOGGER.error("Stream did not complete normally! streamErrored={}, errorRef={}", - streamErrored.get(), errorRef.get(), errorRef.get()); - } - assertTrue(streamCompleted.get(), "Stream should complete normally when QueueClosedEvent is received"); - assertFalse(streamErrored.get(), "Stream should not error on QueueClosedEvent"); - assertNull(errorRef.get(), "Should not receive error when stream completes gracefully"); - } - - @Test - public void testPoisonPillGenerationOnTaskFinalization() throws Exception { - String taskId = "poison-pill-gen-test-" + System.currentTimeMillis(); - String contextId = "test-context-" + System.currentTimeMillis(); - - // Clear any previous events - testConsumer.clear(); - - // Create a task that will be completed (finalized) - Message completeMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("complete"))) - .taskId(taskId) - .messageId("complete-msg-" + System.currentTimeMillis()) - .contextId(contextId) - .build(); - - CountDownLatch completeLatch = new CountDownLatch(1); - AtomicReference finalTask = new AtomicReference<>(); - - nonStreamingClient.sendMessage(completeMessage, List.of((ClientEvent event, AgentCard card) -> { - if (event instanceof TaskEvent taskEvent) { - finalTask.set(taskEvent.getTask()); - // Count down for any task event - we just need the task to be created - completeLatch.countDown(); - } - }), (Throwable error) -> { - completeLatch.countDown(); - }); - - assertTrue(completeLatch.await(15, TimeUnit.SECONDS), "Task creation timed out"); - Task createdTask = finalTask.get(); - assertNotNull(createdTask, "Task should be created"); - - // The task should complete very quickly since it's a simple operation - // Wait a moment to ensure all events have been enqueued - Thread.sleep(2000); - - // Wait for the QueueClosedEvent to be published to Kafka - // The event should be published automatically because isTaskFinalized() returns true - ReplicatedEventQueueItem poisonPill = testConsumer.waitForClosedEvent(taskId, 30); - assertNotNull(poisonPill, "QueueClosedEvent should be published to Kafka when task is finalized"); - assertTrue(poisonPill.isClosedEvent(), "Event should be marked as closedEvent"); - assertEquals(taskId, poisonPill.getTaskId(), "QueueClosedEvent should have correct task ID"); - - // Verify the event is actually a QueueClosedEvent - assertInstanceOf(QueueClosedEvent.class, poisonPill.getEvent(), - "Event should be a QueueClosedEvent"); - QueueClosedEvent closedEvent = - (QueueClosedEvent) poisonPill.getEvent(); - assertEquals(taskId, closedEvent.getTaskId(), "QueueClosedEvent task ID should match"); - } - - /** - * Checks if an error is a benign stream closed/cancelled error that should be ignored. - * HTTP/2 streams can be cancelled during normal cleanup, which is not an actual error. - * - * @param error the throwable to check (may be null) - * @return true if this is a benign stream closure error that should be ignored - */ - private boolean isStreamClosedError(Throwable error) { - return isStreamClosedError(error, new HashSet<>()); - } - - /** - * Internal recursive implementation with cycle detection to prevent infinite recursion. - * - * @param error the throwable to check - * @param visited set of already-visited throwables to detect cycles - * @return true if this is a benign stream closure error - */ - private boolean isStreamClosedError(Throwable error, Set visited) { - if (error == null || !visited.add(error)) { - // Null or already visited (cycle detected) - return false; - } - - // Check for IOException which includes stream cancellation - if (error instanceof IOException) { - String message = error.getMessage(); - if (message != null) { - // Filter out normal stream closure/cancellation errors - if (message.contains("Stream closed") || - message.contains("Stream") && message.contains("cancelled") || - message.contains("EOF reached") || - message.contains("CANCEL")) { - return true; - } - } - } - - // Check cause recursively with cycle detection - Throwable cause = error.getCause(); - if (cause != null) { - return isStreamClosedError(cause, visited); - } - - return false; - } - -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java deleted file mode 100644 index 547a731fd..000000000 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; - -import jakarta.inject.Inject; - -import io.a2a.extras.queuemanager.replicated.core.ReplicatedQueueManager; -import io.a2a.server.events.QueueManager; -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.Test; - -/** - * Basic test to verify the ReplicatedQueueManager is properly configured. - * For full integration testing with Kafka replication, see KafkaReplicationIntegrationTest. - */ -@QuarkusTest -public class ReplicatedQueueManagerTest { - - @Inject - QueueManager queueManager; - - @Test - public void testReplicationSystemIsConfigured() { - // Verify that we're using the ReplicatedQueueManager - assertInstanceOf(ReplicatedQueueManager.class, queueManager); - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java deleted file mode 100644 index 3461ab7d4..000000000 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentCardProducer.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests; - - -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.AgentInterface; -import io.a2a.spec.TransportProtocol; -import io.quarkus.arc.profile.IfBuildProfile; - -/** - * Produces the AgentCard for replicated queue manager integration tests. - */ -@IfBuildProfile("test") -@ApplicationScoped -public class ReplicationTestAgentCardProducer { - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return AgentCard.builder() - .name("replication-test-agent") - .description("Test agent for replicated queue manager integration testing") - .version("1.0.0") - .documentationUrl("http://localhost:8081/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:8081"))) - .build(); - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java deleted file mode 100644 index 8e934df7e..000000000 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests; - -import java.util.List; - -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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import io.quarkus.arc.profile.IfBuildProfile; - -/** - * Test AgentExecutor for replicated queue manager integration testing. - * Handles different message types to trigger various events that should be replicated. - */ -@IfBuildProfile("test") -@ApplicationScoped -public class ReplicationTestAgentExecutor { - - @Produces - public AgentExecutor agentExecutor() { - return new AgentExecutor() { - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - String lastText = getLastTextPart(context.getMessage()); - - switch (lastText) { - case "create": - // Submit task - this should trigger TaskStatusUpdateEvent - agentEmitter.submit(); - break; - case "working": - // Move task to WORKING state without completing - keeps queue alive - agentEmitter.submit(); - agentEmitter.startWork(); - break; - case "complete": - // Complete the task - should trigger poison pill generation - agentEmitter.submit(); - agentEmitter.startWork(); - agentEmitter.addArtifact(List.of(new TextPart("Task completed"))); - agentEmitter.complete(); - break; - default: - throw new InvalidRequestError("Unknown command: " + lastText); - } - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - agentEmitter.cancel(); - } - }; - } - - private String getLastTextPart(Message message) throws A2AError { - if (message.parts().isEmpty()) { - throw new InvalidRequestError("No parts in message"); - } - Part part = message.parts().get(message.parts().size() - 1); - if (part instanceof TextPart) { - return ((TextPart) part).text(); - } - throw new InvalidRequestError("Last part is not text"); - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java deleted file mode 100644 index a7edd13d3..000000000 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java +++ /dev/null @@ -1,174 +0,0 @@ -package io.a2a.extras.queuemanager.replicated.tests; - -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import jakarta.enterprise.context.ApplicationScoped; - -import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.quarkus.arc.profile.IfBuildProfile; -import org.eclipse.microprofile.reactive.messaging.Incoming; - -/** - * Test consumer for Kafka replicated events using reactive messaging. - * Uses a separate incoming channel to avoid interfering with the main application consumer. - */ -@IfBuildProfile("test") -@ApplicationScoped -public class TestKafkaEventConsumer { - - private final ConcurrentLinkedQueue receivedEvents = new ConcurrentLinkedQueue<>(); - private volatile CountDownLatch eventLatch; - - @Incoming("test-replicated-events-in") - public void onTestReplicatedEvent(String jsonMessage) { - try { - ReplicatedEventQueueItem event = JsonUtil.fromJson(jsonMessage, ReplicatedEventQueueItem.class); - receivedEvents.offer(event); - - // Signal any waiting threads - if (eventLatch != null) { - eventLatch.countDown(); - } - } catch (Exception e) { - // Log error but don't fail the message processing - System.err.println("Failed to process test Kafka message: " + e.getMessage()); - throw new RuntimeException(e); - } - } - - /** - * Wait for an event matching the given task ID. - * @param taskId the task ID to wait for - * @param timeoutSeconds maximum time to wait - * @return the matching ReplicatedEventQueueItem, or null if timeout - */ - public ReplicatedEventQueueItem waitForEvent(String taskId, int timeoutSeconds) throws InterruptedException { - // Check if we already have the event - ReplicatedEventQueueItem existing = findEventByTaskId(taskId); - if (existing != null) { - return existing; - } - - // Set up latch to wait for new events - eventLatch = new CountDownLatch(1); - - try { - // Wait for new events - boolean received = eventLatch.await(timeoutSeconds, TimeUnit.SECONDS); - if (received) { - // Check again for the event - return findEventByTaskId(taskId); - } - return null; - } finally { - eventLatch = null; - } - } - - /** - * Wait for an event matching the given task ID and containing specific content. - * @param taskId the task ID to wait for - * @param contentMatch a string that must be present in the event - * @param timeoutSeconds maximum time to wait - * @return the matching ReplicatedEventQueueItem, or null if timeout - */ - public ReplicatedEventQueueItem waitForEventWithContent(String taskId, String contentMatch, int timeoutSeconds) throws InterruptedException { - // Check if we already have the event - ReplicatedEventQueueItem existing = findEventByTaskIdWithContent(taskId, contentMatch); - if (existing != null) { - return existing; - } - - // Set up latch to wait for new events - eventLatch = new CountDownLatch(1); - - try { - // Wait for new events - boolean received = eventLatch.await(timeoutSeconds, TimeUnit.SECONDS); - if (received) { - // Check again for the event - return findEventByTaskIdWithContent(taskId, contentMatch); - } - return null; - } finally { - eventLatch = null; - } - } - - /** - * Wait for a QueueClosedEvent matching the given task ID. - * @param taskId the task ID to wait for - * @param timeoutSeconds maximum time to wait - * @return the matching ReplicatedEventQueueItem with QueueClosedEvent, or null if timeout - */ - public ReplicatedEventQueueItem waitForClosedEvent(String taskId, int timeoutSeconds) throws InterruptedException { - // Check if we already have the event - ReplicatedEventQueueItem existing = findClosedEventByTaskId(taskId); - if (existing != null) { - return existing; - } - - // Set up latch to wait for new events - eventLatch = new CountDownLatch(1); - - try { - // Wait for new events - boolean received = eventLatch.await(timeoutSeconds, TimeUnit.SECONDS); - if (received) { - // Check again for the event - return findClosedEventByTaskId(taskId); - } - return null; - } finally { - eventLatch = null; - } - } - - /** - * Find an event by task ID in the received events. - */ - private ReplicatedEventQueueItem findEventByTaskId(String taskId) { - return receivedEvents.stream() - .filter(event -> taskId.equals(event.getTaskId())) - .findFirst() - .orElse(null); - } - - /** - * Find a QueueClosedEvent by task ID in the received events. - */ - private ReplicatedEventQueueItem findClosedEventByTaskId(String taskId) { - return receivedEvents.stream() - .filter(event -> taskId.equals(event.getTaskId()) && event.isClosedEvent()) - .findFirst() - .orElse(null); - } - - /** - * Find an event by task ID and content match in the received events. - */ - private ReplicatedEventQueueItem findEventByTaskIdWithContent(String taskId, String contentMatch) { - return receivedEvents.stream() - .filter(event -> taskId.equals(event.getTaskId()) && - event.getEvent().toString().contains(contentMatch)) - .findFirst() - .orElse(null); - } - - /** - * Clear all received events (useful for test cleanup). - */ - public void clear() { - receivedEvents.clear(); - } - - /** - * Get count of received events. - */ - public int getEventCount() { - return receivedEvents.size(); - } -} \ No newline at end of file diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/resources/application.properties b/extras/queue-manager-replicated/tests-single-instance/src/test/resources/application.properties deleted file mode 100644 index 15aed5bc3..000000000 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/resources/application.properties +++ /dev/null @@ -1,40 +0,0 @@ -# Configure in-memory H2 database for testing -quarkus.datasource."a2a-java".db-kind=h2 -quarkus.datasource."a2a-java".jdbc.url=jdbc:h2:mem:test -quarkus.hibernate-orm."a2a-java".datasource=a2a-java -quarkus.hibernate-orm."a2a-java".database.generation=drop-and-create -quarkus.hibernate-orm."a2a-java".packages=io.a2a.extras.taskstore.database.jpa - -# Configure the outgoing channel (QueueManager -> Kafka) -mp.messaging.outgoing.replicated-events-out.connector=smallrye-kafka -mp.messaging.outgoing.replicated-events-out.topic=replicated-events -mp.messaging.outgoing.replicated-events-out.value.serializer=org.apache.kafka.common.serialization.StringSerializer - -# Configure the incoming channel (Kafka -> QueueManager) -mp.messaging.incoming.replicated-events-in.connector=smallrye-kafka -mp.messaging.incoming.replicated-events-in.topic=replicated-events -mp.messaging.incoming.replicated-events-in.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer - -# Dev Services for Kafka will automatically start a broker for us -quarkus.kafka.devservices.enabled=true - -# Enhanced configuration for faster and more reliable tests -quarkus.kafka.devservices.topic-partitions."replicated-events"=1 -mp.messaging.incoming.replicated-events-in.auto.offset.reset=earliest - -# Test consumer channel - uses same topic but different consumer group -mp.messaging.incoming.test-replicated-events-in.connector=smallrye-kafka -mp.messaging.incoming.test-replicated-events-in.topic=replicated-events -mp.messaging.incoming.test-replicated-events-in.auto.offset.reset=earliest -mp.messaging.incoming.test-replicated-events-in.group.id=test-consumer-group - -# Reduce timeouts for faster tests -quarkus.messaging.kafka.health.timeout=5s - -# Enable debug logging for queue lifecycle and Kafka -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.extras.queuemanager.replicated".level=DEBUG -quarkus.log.category."io.a2a.client".level=DEBUG -quarkus.log.category."io.smallrye.reactive.messaging".level=DEBUG - diff --git a/extras/task-store-database-jpa/README.md b/extras/task-store-database-jpa/README.md deleted file mode 100644 index eb89611bd..000000000 --- a/extras/task-store-database-jpa/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# A2A Java SDK - JPA Database TaskStore - -This module provides a JPA-based implementation of the `TaskStore` interface that persists tasks to a relational database instead of keeping them in memory. - -The persistence is done with the Jakarta Persistence API, so this should be suitable for any JPA 3.0+ provider and Jakarta EE application server. - -## Quick Start - -### 1. Add Dependency - -Add this module to your project's `pom.xml`: - -```xml - - io.github.a2asdk - a2a-java-extras-task-store-database-jpa - ${a2a.version} - -``` - -The `JpaDatabaseTaskStore` is annotated in such a way that it should take precedence over the default `InMemoryTaskStore`. Hence, it is a drop-in replacement. - -### 2. Configure Database - -The following examples assume you are using PostgreSQL as your database. To use another database, adjust as needed for your environment. - -#### For Quarkus Reference Servers - -Add to your `application.properties`: - -```properties -# Database configuration -quarkus.datasource.db-kind=postgresql -quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/a2a_db -quarkus.datasource.username=your_username -quarkus.datasource.password=your_password - -# Hibernate configuration -quarkus.hibernate-orm.database.generation=update -``` - -#### For WildFly/Jakarta EE Servers - -Create or update your `persistence.xml`: - -```xml - - - - java:jboss/datasources/A2ADataSource - - io.a2a.extras.taskstore.database.jpa.JpaTask - true - - - - - - - - -``` - -### 3. Database Schema - -The module will automatically create the required table: - -```sql -CREATE TABLE a2a_tasks ( - task_id VARCHAR(255) PRIMARY KEY, - task_data TEXT NOT NULL -); -``` - -## Configuration Options - -### Persistence Unit Name - -The module uses the persistence unit name `"a2a-java"`. Ensure your `persistence.xml` defines a persistence unit with this name. \ No newline at end of file diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml deleted file mode 100644 index 9bfbd8a15..000000000 --- a/extras/task-store-database-jpa/pom.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-extras-task-store-database-jpa - - jar - - Java A2A Extras: JPA Database TaskStore - Java SDK for the Agent2Agent Protocol (A2A) - Extras - JPA Database TaskStore - - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-extras-common - - - jakarta.annotation - jakarta.annotation-api - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - jakarta.persistence - jakarta.persistence-api - - - org.slf4j - slf4j-api - - - - io.quarkus - quarkus-junit5 - test - - - io.quarkus - quarkus-rest-client - test - - - org.junit.jupiter - junit-jupiter-api - test - - - io.rest-assured - rest-assured - test - - - jakarta.transaction - jakarta.transaction-api - - - io.quarkus - quarkus-hibernate-orm - test - - - io.quarkus - quarkus-jdbc-h2 - test - - - - ${project.groupId} - a2a-java-sdk-reference-jsonrpc - test - - - ${project.groupId} - a2a-java-sdk-client-transport-jsonrpc - test - - - ${project.groupId} - a2a-java-sdk-client - test - - - io.quarkus - quarkus-reactive-routes - test - - - \ No newline at end of file diff --git a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java b/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java deleted file mode 100644 index 086e640e3..000000000 --- a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java +++ /dev/null @@ -1,371 +0,0 @@ -package io.a2a.extras.taskstore.database.jpa; - -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; - -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Priority; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.event.Event; -import jakarta.enterprise.inject.Alternative; -import jakarta.inject.Inject; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.persistence.TypedQuery; -import jakarta.transaction.Transactional; - -import io.a2a.extras.common.events.TaskFinalizedEvent; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.config.A2AConfigProvider; -import io.a2a.server.tasks.TaskStateProvider; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Artifact; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.util.PageToken; -import io.a2a.spec.Task; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -@Alternative -@Priority(50) -public class JpaDatabaseTaskStore implements TaskStore, TaskStateProvider { - - private static final Logger LOGGER = LoggerFactory.getLogger(JpaDatabaseTaskStore.class); - private static final String A2A_REPLICATION_GRACE_PERIOD_SECONDS = "a2a.replication.grace-period-seconds"; - - @PersistenceContext(unitName = "a2a-java") - EntityManager em; - - @Inject - Event taskFinalizedEvent; - - @Inject - A2AConfigProvider configProvider; - - /** - * Grace period for task finalization in replicated scenarios (seconds). - * After a task reaches a final state, this is the minimum time to wait before cleanup - * to allow replicated events to arrive and be processed. - *

- * Property: {@code a2a.replication.grace-period-seconds}
- * Default: 15
- * Note: Property override requires a configurable {@link A2AConfigProvider} on the classpath. - */ - long gracePeriodSeconds; - - @PostConstruct - void initConfig() { - gracePeriodSeconds = Long.parseLong(configProvider.getValue(A2A_REPLICATION_GRACE_PERIOD_SECONDS)); - } - - @Transactional - @Override - public void save(Task task, boolean isReplicated) { - LOGGER.debug("Saving task with ID: {} (replicated: {})", task.id(), isReplicated); - try { - JpaTask jpaTask = JpaTask.createFromTask(task); - em.merge(jpaTask); - LOGGER.debug("Persisted/updated task with ID: {}", task.id()); - - // Only fire TaskFinalizedEvent for locally-generated final states, NOT for replicated events - // This prevents feedback loops where receiving a replicated final task triggers another replication - if (!isReplicated && task.status() != null && task.status().state() != null && task.status().state().isFinal()) { - // Fire CDI event if task reached final state - // IMPORTANT: The event will be delivered AFTER transaction commits (AFTER_SUCCESS observers) - // This ensures the task's final state is durably stored before the final task and poison pill are sent - LOGGER.debug("Task {} is in final state, firing TaskFinalizedEvent with full Task", task.id()); - taskFinalizedEvent.fire(new TaskFinalizedEvent(task.id(), task)); - } else if (isReplicated && task.status() != null && task.status().state() != null && task.status().state().isFinal()) { - LOGGER.debug("Task {} is in final state but from replication - NOT firing TaskFinalizedEvent (prevents feedback loop)", task.id()); - } - } catch (JsonProcessingException e) { - LOGGER.error("Failed to serialize task with ID: {}", task.id(), e); - throw new RuntimeException("Failed to serialize task with ID: " + task.id(), e); - } - } - - @Transactional - @Override - public Task get(String taskId) { - LOGGER.debug("Retrieving task with ID: {}", taskId); - JpaTask jpaTask = em.find(JpaTask.class, taskId); - if (jpaTask == null) { - LOGGER.debug("Task not found with ID: {}", taskId); - return null; - } - - try { - Task task = jpaTask.getTask(); - LOGGER.debug("Successfully retrieved task with ID: {}", taskId); - return task; - } catch (JsonProcessingException e) { - LOGGER.error("Failed to deserialize task with ID: {}", taskId, e); - throw new RuntimeException("Failed to deserialize task with ID: " + taskId, e); - } - } - - @Transactional - @Override - public void delete(String taskId) { - LOGGER.debug("Deleting task with ID: {}", taskId); - JpaTask jpaTask = em.find(JpaTask.class, taskId); - if (jpaTask != null) { - em.remove(jpaTask); - LOGGER.debug("Successfully deleted task with ID: {}", taskId); - } else { - LOGGER.debug("Task not found for deletion with ID: {}", taskId); - } - } - - /** - * Determines if a task is considered active for queue management purposes. - *

A task is active if:

- *
    - *
  • Its state is not final, OR
  • - *
  • Its state is final but it was finalized within the grace period
  • - *
- *

- * The grace period handles the race condition where events are published to Kafka - * while a task is active, but consumed on a replica node after the task is finalized. - *

- * - * @param taskId the task ID to check - * @return true if the task is active (or recently finalized within grace period), false otherwise - */ - @Transactional - @Override - public boolean isTaskActive(String taskId) { - LOGGER.debug("Checking if task is active: {}", taskId); - - JpaTask jpaTask = em.find(JpaTask.class, taskId); - if (jpaTask == null) { - LOGGER.debug("Task not found, considering inactive: {}", taskId); - return false; - } - - try { - Task task = jpaTask.getTask(); - - // Task is active if not in final state - if (task.status() == null || task.status().state() == null || !task.status().state().isFinal()) { - LOGGER.debug("Task is not in final state, considering active: {}", taskId); - return true; - } - - // Task is in final state - check grace period - Instant finalizedAt = jpaTask.getFinalizedAt(); - if (finalizedAt == null) { - // Should not happen, but defensive: if final state but no timestamp, consider inactive - LOGGER.warn("Task {} is in final state but has no finalizedAt timestamp, considering inactive", taskId); - return false; - } - - Instant gracePeriodEnd = finalizedAt.plus(Duration.ofSeconds(gracePeriodSeconds)); - Instant now = Instant.now(); - - boolean withinGracePeriod = now.isBefore(gracePeriodEnd); - LOGGER.debug("Task {} is final. FinalizedAt: {}, GracePeriodEnd: {}, Now: {}, Active: {}", - taskId, finalizedAt, gracePeriodEnd, now, withinGracePeriod); - - return withinGracePeriod; - - } catch (JsonProcessingException e) { - LOGGER.error("Failed to deserialize task with ID: {}, considering inactive", taskId, e); - return false; - } - } - - /** - * Determines if a task is in a final state, ignoring the grace period. - *

- * This method performs an immediate check: returns true only if the task - * is in a final state (COMPLETED, CANCELED, FAILED, etc.), regardless of when - * it was finalized. - *

- *

- * This method is used by the MainQueue.onClose callback to decide whether - * to publish the QueueClosedEvent "poison pill". By ignoring the grace period, - * it ensures that subscribers are terminated immediately when the task is done, - * providing responsive UX. - *

- * - * @param taskId the task ID to check - * @return true if the task is in a final state (ignoring grace period), false otherwise - */ - @Transactional - @Override - public boolean isTaskFinalized(String taskId) { - LOGGER.debug("Checking if task is finalized: {}", taskId); - - JpaTask jpaTask = em.find(JpaTask.class, taskId); - if (jpaTask == null) { - LOGGER.debug("Task not found, considering not finalized: {}", taskId); - return false; - } - - try { - Task task = jpaTask.getTask(); - - // Task is finalized if in final state (ignore grace period) - boolean isFinalized = task.status() != null - && task.status().state() != null - && task.status().state().isFinal(); - - LOGGER.debug("Task {} finalization check: {}", taskId, isFinalized); - return isFinalized; - - } catch (JsonProcessingException e) { - LOGGER.error("Failed to deserialize task with ID: {}, considering not finalized", taskId, e); - return false; - } - } - - @Transactional - @Override - public ListTasksResult list(ListTasksParams params) { - LOGGER.debug("Listing tasks with params: contextId={}, status={}, pageSize={}, pageToken={}", - params.contextId(), params.status(), params.pageSize(), params.pageToken()); - - // Parse pageToken once at the beginning - PageToken pageToken = PageToken.fromString(params.pageToken()); - Instant tokenTimestamp = pageToken != null ? pageToken.timestamp() : null; - String tokenId = pageToken != null ? pageToken.id() : null; - - // Build dynamic JPQL query with WHERE clauses for filtering - StringBuilder queryBuilder = new StringBuilder("SELECT t FROM JpaTask t WHERE 1=1"); - StringBuilder countQueryBuilder = new StringBuilder("SELECT COUNT(t) FROM JpaTask t WHERE 1=1"); - - // Apply contextId filter using denormalized column - if (params.contextId() != null) { - queryBuilder.append(" AND t.contextId = :contextId"); - countQueryBuilder.append(" AND t.contextId = :contextId"); - } - - // Apply status filter using denormalized column - if (params.status() != null) { - queryBuilder.append(" AND t.state = :state"); - countQueryBuilder.append(" AND t.state = :state"); - } - - // Apply statusTimestampAfter filter using denormalized timestamp column - if (params.statusTimestampAfter() != null) { - queryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); - countQueryBuilder.append(" AND t.statusTimestamp > :statusTimestampAfter"); - } - - // Apply pagination cursor using keyset pagination for composite sort (timestamp DESC, id ASC) - if (tokenTimestamp != null) { - // Keyset pagination: get tasks where timestamp < tokenTimestamp OR (timestamp = tokenTimestamp AND id > tokenId) - queryBuilder.append(" AND (t.statusTimestamp < :tokenTimestamp OR (t.statusTimestamp = :tokenTimestamp AND t.id > :tokenId))"); - } - - // Sort by status timestamp descending (most recent first), then by ID for stable ordering - queryBuilder.append(" ORDER BY t.statusTimestamp DESC, t.id ASC"); - - // Create and configure the main query - TypedQuery query = em.createQuery(queryBuilder.toString(), JpaTask.class); - - // Set filter parameters - if (params.contextId() != null) { - query.setParameter("contextId", params.contextId()); - } - if (params.status() != null) { - query.setParameter("state", params.status().name()); - } - if (params.statusTimestampAfter() != null) { - query.setParameter("statusTimestampAfter", params.statusTimestampAfter()); - } - if (tokenTimestamp != null) { - query.setParameter("tokenTimestamp", tokenTimestamp); - query.setParameter("tokenId", tokenId); - } - - // Apply page size limit (+1 to check for next page) - int pageSize = params.getEffectivePageSize(); - query.setMaxResults(pageSize + 1); - - // Execute query and deserialize tasks - List jpaTasksPage = query.getResultList(); - - // Determine if there are more results - boolean hasMore = jpaTasksPage.size() > pageSize; - if (hasMore) { - jpaTasksPage = jpaTasksPage.subList(0, pageSize); - } - - // Get total count of matching tasks - TypedQuery countQuery = em.createQuery(countQueryBuilder.toString(), Long.class); - if (params.contextId() != null) { - countQuery.setParameter("contextId", params.contextId()); - } - if (params.status() != null) { - countQuery.setParameter("state", params.status().name()); - } - if (params.statusTimestampAfter() != null) { - countQuery.setParameter("statusTimestampAfter", params.statusTimestampAfter()); - } - int totalSize = countQuery.getSingleResult().intValue(); - - // Deserialize tasks from JSON - List tasks = new ArrayList<>(); - for (JpaTask jpaTask : jpaTasksPage) { - try { - tasks.add(jpaTask.getTask()); - } catch (JsonProcessingException e) { - LOGGER.error("Failed to deserialize task with ID: {}", jpaTask.getId(), e); - throw new RuntimeException("Failed to deserialize task with ID: " + jpaTask.getId(), e); - } - } - - // Determine next page token (timestamp:ID of last task if there are more results) - // Format: "timestamp_millis:taskId" for keyset pagination - String nextPageToken = null; - if (hasMore && !tasks.isEmpty()) { - Task lastTask = tasks.get(tasks.size() - 1); - // All tasks have timestamps (TaskStatus canonical constructor ensures this) - Instant timestamp = lastTask.status().timestamp().toInstant(); - nextPageToken = new PageToken(timestamp, lastTask.id()).toString(); - } - - // Apply post-processing transformations (history limiting, artifact removal) - int historyLength = params.getEffectiveHistoryLength(); - boolean includeArtifacts = params.shouldIncludeArtifacts(); - - List transformedTasks = tasks.stream() - .map(task -> transformTask(task, historyLength, includeArtifacts)) - .toList(); - - LOGGER.debug("Returning {} tasks out of {} total", transformedTasks.size(), totalSize); - return new ListTasksResult(transformedTasks, totalSize, transformedTasks.size(), nextPageToken); - } - - private Task transformTask(Task task, int historyLength, boolean includeArtifacts) { - // Limit history if needed (keep most recent N messages) - List history = task.history(); - if (historyLength == 0) { - // When historyLength is 0, return empty history - history = List.of(); - } else if (historyLength > 0 && history != null && history.size() > historyLength) { - history = history.subList(history.size() - historyLength, history.size()); - } - - // Remove artifacts if not requested - List artifacts = includeArtifacts ? task.artifacts() : List.of(); - - // If no transformation needed, return original task - if (history == task.history() && artifacts == task.artifacts()) { - return task; - } - - // Build new task with transformed data - return Task.builder(task) - .artifacts(artifacts) - .history(history) - .build(); - } -} diff --git a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java b/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java deleted file mode 100644 index 5a9477f2f..000000000 --- a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java +++ /dev/null @@ -1,160 +0,0 @@ -package io.a2a.extras.taskstore.database.jpa; - -import java.time.Instant; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import jakarta.persistence.Transient; - -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Task; - -@Entity -@Table(name = "a2a_tasks") -public class JpaTask { - @Id - @Column(name = "task_id") - private String id; - - @Column(name = "context_id") - private String contextId; - - @Column(name = "state") - private String state; - - @Column(name = "status_timestamp") - private Instant statusTimestamp; - - @Column(name = "task_data", columnDefinition = "TEXT", nullable = false) - private String taskJson; - - @Column(name = "finalized_at") - private Instant finalizedAt; - - @Transient - private Task task; - - // Default constructor required by JPA - public JpaTask() { - } - - public JpaTask(String id, String taskJson) { - this.id = id; - this.taskJson = taskJson; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getContextId() { - return contextId; - } - - public void setContextId(String contextId) { - this.contextId = contextId; - } - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } - - public Instant getStatusTimestamp() { - return statusTimestamp; - } - - public void setStatusTimestamp(Instant statusTimestamp) { - this.statusTimestamp = statusTimestamp; - } - - public String getTaskJson() { - return taskJson; - } - - public void setTaskJson(String taskJson) { - this.taskJson = taskJson; - } - - public Instant getFinalizedAt() { - return finalizedAt; - } - - /** - * Sets the finalized timestamp for this task. - *

- * This method is idempotent - it only sets the timestamp on the first transition - * to a final state, as a defense-in-depth measure complementing the existing - * application logic that prevents modifications to final tasks. - *

- * - * @param finalizedAt the timestamp when the task was finalized - * @param isFinalState whether the current task state is final - */ - public void setFinalizedAt(Instant finalizedAt, boolean isFinalState) { - if (this.finalizedAt == null && isFinalState) { - this.finalizedAt = finalizedAt; - } - } - - public Task getTask() throws JsonProcessingException { - if (task == null) { - this.task = JsonUtil.fromJson(taskJson, Task.class); - } - return task; - } - - public void setTask(Task task) throws JsonProcessingException { - taskJson = JsonUtil.toJson(task); - if (id == null) { - id = task.id(); - } - this.task = task; - updateDenormalizedFields(task); - updateFinalizedTimestamp(task); - } - - static JpaTask createFromTask(Task task) throws JsonProcessingException { - String json = JsonUtil.toJson(task); - JpaTask jpaTask = new JpaTask(task.id(), json); - jpaTask.task = task; - jpaTask.updateDenormalizedFields(task); - jpaTask.updateFinalizedTimestamp(task); - return jpaTask; - } - - /** - * Updates denormalized fields (contextId, state, statusTimestamp) from the task object. - * These fields are duplicated from the JSON to enable efficient querying. - * - * @param task the task to extract fields from - */ - private void updateDenormalizedFields(Task task) { - this.contextId = task.contextId(); - io.a2a.spec.TaskState taskState = task.status().state(); - this.state = taskState.name(); - // Extract status timestamp for efficient querying and sorting - // Truncate to milliseconds for keyset pagination consistency (pageToken uses millis) - this.statusTimestamp = task.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS); - } - - /** - * Updates the finalizedAt timestamp if the task is in a final state. - * This method is idempotent and only sets the timestamp on first finalization. - * - * @param task the task to check for finalization - */ - private void updateFinalizedTimestamp(Task task) { - setFinalizedAt(Instant.now(), task.status().state().isFinal()); - } -} diff --git a/extras/task-store-database-jpa/src/main/resources/META-INF/a2a-defaults.properties b/extras/task-store-database-jpa/src/main/resources/META-INF/a2a-defaults.properties deleted file mode 100644 index c01c5e60a..000000000 --- a/extras/task-store-database-jpa/src/main/resources/META-INF/a2a-defaults.properties +++ /dev/null @@ -1,6 +0,0 @@ -# A2A JPA Database Task Store Default Configuration - -# Grace period for task finalization in replicated scenarios (seconds) -# After a task reaches a final state, this is the minimum time to wait before cleanup -# to allow replicated events to arrive and be processed -a2a.replication.grace-period-seconds=15 diff --git a/extras/task-store-database-jpa/src/main/resources/META-INF/beans.xml b/extras/task-store-database-jpa/src/main/resources/META-INF/beans.xml deleted file mode 100644 index ffc8abb42..000000000 --- a/extras/task-store-database-jpa/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java deleted file mode 100644 index 9b716c705..000000000 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreIntegrationTest.java +++ /dev/null @@ -1,153 +0,0 @@ -package io.a2a.extras.taskstore.database.jpa; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import jakarta.inject.Inject; - -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TextPart; -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * End-to-end integration test that verifies the JPA TaskStore works correctly - * with the full client-server flow using the Client API. - */ -@QuarkusTest -public class JpaDatabaseTaskStoreIntegrationTest { - - @Inject - TaskStore taskStore; - - @Inject - @PublicAgentCard - AgentCard agentCard; - - private Client client; - - @BeforeEach - public void setup() throws A2AClientException { - ClientConfig clientConfig = new ClientConfig.Builder() - .setStreaming(false) - .build(); - - client = Client.builder(agentCard) - .clientConfig(clientConfig) - .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()) - .build(); - } - - @Test - public void testIsJpaDatabaseTaskStore() { - assertInstanceOf(JpaDatabaseTaskStore.class, taskStore); - } - - @Test - public void testJpaDatabaseTaskStore() throws Exception { - final String taskId = "test-task-1"; - final String contextId = "contextId"; - - // Send a message creating the Task - assertNull(taskStore.get(taskId)); - Message userMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("create"))) - .taskId(taskId) - .messageId("test-msg-1") - .contextId(contextId) - .build(); - - CountDownLatch latch = new CountDownLatch(1); - AtomicReference taskRef = new AtomicReference<>(); - - java.util.function.BiConsumer consumer = (event, card) -> { - if (event instanceof TaskEvent taskEvent) { - taskRef.set(taskEvent.getTask()); - latch.countDown(); - } - }; - - client.sendMessage(userMessage, List.of(consumer), (Throwable e) -> { - latch.countDown(); - }); - - assertTrue(latch.await(10, TimeUnit.SECONDS), "Timeout waiting for task creation"); - Task createdTask = taskRef.get(); - assertNotNull(createdTask); - assertEquals(0, createdTask.artifacts().size()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, createdTask.status().state()); - - // Send a message updating the Task - userMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("add-artifact"))) - .taskId(taskId) - .messageId("test-msg-2") - .contextId(contextId) - .build(); - - CountDownLatch latch2 = new CountDownLatch(1); - AtomicReference taskRef2 = new AtomicReference<>(); - - consumer = (event, card) -> { - if (event instanceof TaskEvent taskEvent) { - taskRef2.set(taskEvent.getTask()); - latch2.countDown(); - } - }; - - client.sendMessage(userMessage, List.of(consumer), (Throwable e) -> { - latch2.countDown(); - }); - - assertTrue(latch2.await(10, TimeUnit.SECONDS), "Timeout waiting for task creation"); - Task updatedTask = taskRef2.get(); - assertNotNull(updatedTask); - assertEquals(1, updatedTask.artifacts().size()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, updatedTask.status().state()); - - Task retrievedTask = client.getTask(new TaskQueryParams(taskId), null); - assertNotNull(retrievedTask); - assertEquals(1, retrievedTask.artifacts().size()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, retrievedTask.status().state()); - - // Cancel the task - Task cancelledTask = client.cancelTask(new TaskIdParams(taskId), null); - assertNotNull(cancelledTask); - assertEquals(1, cancelledTask.artifacts().size()); - assertEquals(TaskState.TASK_STATE_CANCELED, cancelledTask.status().state()); - - Task retrievedCancelledTask = client.getTask(new TaskQueryParams(taskId), null); - assertNotNull(retrievedCancelledTask); - assertEquals(1, retrievedCancelledTask.artifacts().size()); - assertEquals(TaskState.TASK_STATE_CANCELED, retrievedCancelledTask.status().state()); - - // None of the framework code deletes tasks, so just do this manually - taskStore.delete(taskId); - } -} diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java deleted file mode 100644 index 74164e39e..000000000 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java +++ /dev/null @@ -1,796 +0,0 @@ -package io.a2a.extras.taskstore.database.jpa; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Artifact; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.Test; - -@QuarkusTest -public class JpaDatabaseTaskStoreTest { - - @Inject - TaskStore taskStore; - - - @Inject - jakarta.persistence.EntityManager entityManager; - - @Test - public void testIsJpaDatabaseTaskStore() { - assertInstanceOf(JpaDatabaseTaskStore.class, taskStore); - } - - @Test - @Transactional - public void testSaveAndRetrieveTask() { - // Create a test task - Task task = Task.builder() - .id("test-task-1") - .contextId("test-context-1") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .metadata(new HashMap<>()) - .build(); - - // Save the task - taskStore.save(task, false); - - // Retrieve the task - Task retrieved = taskStore.get("test-task-1"); - - assertNotNull(retrieved); - assertEquals("test-task-1", retrieved.id()); - assertEquals("test-context-1", retrieved.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, retrieved.status().state()); - } - - @Test - @Transactional - public void testSaveAndRetrieveTaskWithHistory() { - // Create a message for the task history - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("Hello, agent!"))) - .messageId("msg-1") - .build(); - - // Create a task with history - Task task = Task.builder() - .id("test-task-2") - .contextId("test-context-2") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .history(Collections.singletonList(message)) - .build(); - - // Save the task - taskStore.save(task, false); - - // Retrieve the task - Task retrieved = taskStore.get("test-task-2"); - - assertNotNull(retrieved); - assertEquals("test-task-2", retrieved.id()); - assertEquals("test-context-2", retrieved.contextId()); - assertEquals(TaskState.TASK_STATE_WORKING, retrieved.status().state()); - assertEquals(1, retrieved.history().size()); - assertEquals("msg-1", retrieved.history().get(0).messageId()); - assertEquals("Hello, agent!", ((TextPart) retrieved.history().get(0).parts().get(0)).text()); - } - - @Test - @Transactional - public void testUpdateExistingTask() { - // Create and save initial task - Task initialTask = Task.builder() - .id("test-task-3") - .contextId("test-context-3") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - taskStore.save(initialTask, false); - - // Update the task - Task updatedTask = Task.builder() - .id("test-task-3") - .contextId("test-context-3") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - taskStore.save(updatedTask, false); - - // Retrieve and verify the update - Task retrieved = taskStore.get("test-task-3"); - - assertNotNull(retrieved); - assertEquals("test-task-3", retrieved.id()); - assertEquals(TaskState.TASK_STATE_COMPLETED, retrieved.status().state()); - } - - @Test - @Transactional - public void testGetNonExistentTask() { - Task retrieved = taskStore.get("non-existent-task"); - assertNull(retrieved); - } - - @Test - @Transactional - public void testDeleteTask() { - // Create and save a task - Task task = Task.builder() - .id("test-task-4") - .contextId("test-context-4") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - taskStore.save(task, false); - - // Verify it exists - assertNotNull(taskStore.get("test-task-4")); - - // Delete the task - taskStore.delete("test-task-4"); - - // Verify it's gone - assertNull(taskStore.get("test-task-4")); - } - - @Test - @Transactional - public void testDeleteNonExistentTask() { - // This should not throw an exception - taskStore.delete("non-existent-task"); - } - - @Test - @Transactional - public void testTaskWithComplexMetadata() { - // Create a task with complex metadata - HashMap metadata = new HashMap<>(); - metadata.put("key1", "value1"); - metadata.put("key2", 42); - metadata.put("key3", true); - - Task task = Task.builder() - .id("test-task-5") - .contextId("test-context-5") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .metadata(metadata) - .build(); - - // Save and retrieve - taskStore.save(task, false); - Task retrieved = taskStore.get("test-task-5"); - - assertNotNull(retrieved); - assertEquals("test-task-5", retrieved.id()); - assertNotNull(retrieved.metadata()); - assertEquals("value1", retrieved.metadata().get("key1")); - assertEquals(42, ((Number)retrieved.metadata().get("key2")).intValue()); - assertEquals(true, retrieved.metadata().get("key3")); - } - - @Test - @Transactional - public void testIsTaskActiveForNonFinalTask() { - // Create a task in non-final state - Task task = Task.builder() - .id("test-task-active-1") - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - taskStore.save(task, false); - - // Task should be active (not in final state) - JpaDatabaseTaskStore jpaDatabaseTaskStore = (JpaDatabaseTaskStore) taskStore; - boolean isActive = jpaDatabaseTaskStore.isTaskActive("test-task-active-1"); - - assertEquals(true, isActive, "Non-final task should be active"); - } - - @Test - @Transactional - public void testIsTaskActiveForFinalTaskWithinGracePeriod() { - // Create a task and update it to final state - Task task = Task.builder() - .id("test-task-active-2") - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - taskStore.save(task, false); - - // Update to final state - Task finalTask = Task.builder() - .id("test-task-active-2") - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - taskStore.save(finalTask, false); - - // Task should be active (within grace period - default 15 seconds) - JpaDatabaseTaskStore jpaDatabaseTaskStore = (JpaDatabaseTaskStore) taskStore; - boolean isActive = jpaDatabaseTaskStore.isTaskActive("test-task-active-2"); - - assertEquals(true, isActive, "Final task within grace period should be active"); - } - - @Test - @Transactional - public void testIsTaskActiveForFinalTaskBeyondGracePeriod() { - // Create and save a task in final state - Task task = Task.builder() - .id("test-task-active-3") - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - taskStore.save(task, false); - - // Directly update the finalizedAt timestamp to 20 seconds in the past - // (beyond the default 15-second grace period) - JpaTask jpaTask = entityManager.find(JpaTask.class, "test-task-active-3"); - assertNotNull(jpaTask); - - // Manually set finalizedAt to 20 seconds in the past - java.time.Instant pastTime = java.time.Instant.now().minusSeconds(20); - entityManager.createQuery("UPDATE JpaTask j SET j.finalizedAt = :finalizedAt WHERE j.id = :id") - .setParameter("finalizedAt", pastTime) - .setParameter("id", "test-task-active-3") - .executeUpdate(); - - entityManager.flush(); - entityManager.clear(); // Clear persistence context to force fresh read - - // Task should be inactive (beyond grace period) - JpaDatabaseTaskStore jpaDatabaseTaskStore = (JpaDatabaseTaskStore) taskStore; - boolean isActive = jpaDatabaseTaskStore.isTaskActive("test-task-active-3"); - - assertEquals(false, isActive, "Final task beyond grace period should be inactive"); - } - - @Test - @Transactional - public void testIsTaskActiveForNonExistentTask() { - JpaDatabaseTaskStore jpaDatabaseTaskStore = (JpaDatabaseTaskStore) taskStore; - boolean isActive = jpaDatabaseTaskStore.isTaskActive("non-existent-task"); - - assertEquals(false, isActive, "Non-existent task should be inactive"); - } - - // ===== list() method tests ===== - - @Test - @Transactional - public void testListTasksEmpty() { - // List with specific context that has no tasks - ListTasksParams params = ListTasksParams.builder() - .contextId("non-existent-context-12345") - .tenant("tenant") - .build(); - ListTasksResult result = taskStore.list(params); - - assertNotNull(result); - assertEquals(0, result.totalSize()); - assertEquals(0, result.pageSize()); - assertTrue(result.tasks().isEmpty()); - assertNull(result.nextPageToken()); - } - - @Test - @Transactional - public void testListTasksFilterByContextId() { - // Create tasks with different context IDs - Task task1 = Task.builder() - .id("task-context-1") - .contextId("context-A") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - Task task2 = Task.builder() - .id("task-context-2") - .contextId("context-A") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - Task task3 = Task.builder() - .id("task-context-3") - .contextId("context-B") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - taskStore.save(task1, false); - taskStore.save(task2, false); - taskStore.save(task3, false); - - // List tasks for context-A - ListTasksParams params = ListTasksParams.builder() - .contextId("context-A") - .tenant("tenant") - .build(); - ListTasksResult result = taskStore.list(params); - - assertEquals(2, result.totalSize()); - assertEquals(2, result.pageSize()); - assertEquals(2, result.tasks().size()); - assertTrue(result.tasks().stream().allMatch(t -> "context-A".equals(t.contextId()))); - } - - @Test - @Transactional - public void testListTasksFilterByStatus() { - // Create tasks with different statuses - use unique context - Task task1 = Task.builder() - .id("task-status-filter-1") - .contextId("context-status-filter-test") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - Task task2 = Task.builder() - .id("task-status-filter-2") - .contextId("context-status-filter-test") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - Task task3 = Task.builder() - .id("task-status-filter-3") - .contextId("context-status-filter-test") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - taskStore.save(task1, false); - taskStore.save(task2, false); - taskStore.save(task3, false); - - // List only WORKING tasks in this context - ListTasksParams params = ListTasksParams.builder() - .contextId("context-status-filter-test") - .tenant("tenant") - .status(TaskState.TASK_STATE_WORKING) - .build(); - ListTasksResult result = taskStore.list(params); - - assertEquals(1, result.totalSize()); - assertEquals(1, result.pageSize()); - assertEquals(1, result.tasks().size()); - assertEquals(TaskState.TASK_STATE_WORKING, result.tasks().get(0).status().state()); - } - - @Test - @Transactional - public void testListTasksCombinedFilters() { - // Create tasks with various context IDs and statuses - Task task1 = Task.builder() - .id("task-combined-1") - .contextId("context-X") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - Task task2 = Task.builder() - .id("task-combined-2") - .contextId("context-X") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - Task task3 = Task.builder() - .id("task-combined-3") - .contextId("context-Y") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - taskStore.save(task1, false); - taskStore.save(task2, false); - taskStore.save(task3, false); - - // List WORKING tasks in context-X - ListTasksParams params = ListTasksParams.builder() - .contextId("context-X") - .tenant("tenant") - .status(TaskState.TASK_STATE_WORKING) - .build(); - ListTasksResult result = taskStore.list(params); - - assertEquals(1, result.totalSize()); - assertEquals(1, result.pageSize()); - assertEquals("task-combined-2", result.tasks().get(0).id()); - assertEquals("context-X", result.tasks().get(0).contextId()); - assertEquals(TaskState.TASK_STATE_WORKING, result.tasks().get(0).status().state()); - } - - @Test - @Transactional - public void testListTasksPagination() { - // Create 5 tasks with same timestamp to ensure ID-based pagination works - // (With timestamp DESC sorting, same timestamps allow ID ASC tie-breaking) - OffsetDateTime sameTimestamp = OffsetDateTime.now(java.time.ZoneOffset.UTC); - for (int i = 1; i <= 5; i++) { - Task task = Task.builder() - .id("task-page-" + i) - .contextId("context-pagination") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) - .build(); - taskStore.save(task, false); - } - - // First page: pageSize=2 - ListTasksParams params1 = ListTasksParams.builder() - .contextId("context-pagination") - .tenant("tenant") - .pageSize(2) - .build(); - ListTasksResult result1 = taskStore.list(params1); - - assertEquals(5, result1.totalSize()); - assertEquals(2, result1.pageSize()); - assertEquals(2, result1.tasks().size()); - assertNotNull(result1.nextPageToken(), "Should have next page token"); - - // Second page: use pageToken from first page - ListTasksParams params2 = ListTasksParams.builder() - .contextId("context-pagination") - .tenant("tenant") - .pageSize(2) - .pageToken(result1.nextPageToken()) - .build(); - ListTasksResult result2 = taskStore.list(params2); - - assertEquals(5, result2.totalSize()); - assertEquals(2, result2.pageSize()); - assertNotNull(result2.nextPageToken(), "Should have next page token"); - - // Third page: last page - ListTasksParams params3 = ListTasksParams.builder() - .contextId("context-pagination") - .tenant("tenant") - .pageSize(2) - .pageToken(result2.nextPageToken()) - .build(); - ListTasksResult result3 = taskStore.list(params3); - - assertEquals(5, result3.totalSize()); - assertEquals(1, result3.pageSize()); - assertNull(result3.nextPageToken(), "Last page should have no next page token"); - } - - @Test - @Transactional - public void testListTasksPaginationWithDifferentTimestamps() { - // Create tasks with different timestamps to verify keyset pagination - // with composite sort (timestamp DESC, id ASC) - OffsetDateTime now = OffsetDateTime.now(java.time.ZoneOffset.UTC); - - // Task 1: 10 minutes ago, ID="task-diff-a" - Task task1 = Task.builder() - .id("task-diff-a") - .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(10))) - .build(); - taskStore.save(task1, false); - - // Task 2: 5 minutes ago, ID="task-diff-b" - Task task2 = Task.builder() - .id("task-diff-b") - .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(5))) - .build(); - taskStore.save(task2, false); - - // Task 3: 5 minutes ago, ID="task-diff-c" (same timestamp as task2, tests ID tie-breaker) - Task task3 = Task.builder() - .id("task-diff-c") - .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(5))) - .build(); - taskStore.save(task3, false); - - // Task 4: Now, ID="task-diff-d" - Task task4 = Task.builder() - .id("task-diff-d") - .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now)) - .build(); - taskStore.save(task4, false); - - // Task 5: 1 minute ago, ID="task-diff-e" - Task task5 = Task.builder() - .id("task-diff-e") - .contextId("context-diff-timestamps") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, now.minusMinutes(1))) - .build(); - taskStore.save(task5, false); - - // Expected order (timestamp DESC, id ASC): - // 1. task-diff-d (now) - // 2. task-diff-e (1 min ago) - // 3. task-diff-b (5 min ago, ID 'b') - // 4. task-diff-c (5 min ago, ID 'c') - // 5. task-diff-a (10 min ago) - - // Page 1: Get first 2 tasks - ListTasksParams params1 = ListTasksParams.builder() - .contextId("context-diff-timestamps") - .tenant("tenant") - .pageSize(2) - .build(); - ListTasksResult result1 = taskStore.list(params1); - - assertEquals(5, result1.totalSize()); - assertEquals(2, result1.pageSize()); - assertNotNull(result1.nextPageToken(), "Should have next page token"); - - // Verify first page order - assertEquals("task-diff-d", result1.tasks().get(0).id(), "First task should be most recent"); - assertEquals("task-diff-e", result1.tasks().get(1).id(), "Second task should be 1 min ago"); - - // Verify pageToken format: "timestamp_millis:taskId" - assertTrue(result1.nextPageToken().contains(":"), "PageToken should have format timestamp:id"); - String[] tokenParts = result1.nextPageToken().split(":", 2); - assertEquals(2, tokenParts.length, "PageToken should have exactly 2 parts"); - assertEquals("task-diff-e", tokenParts[1], "PageToken should contain last task ID"); - - // Page 2: Get next 2 tasks - ListTasksParams params2 = ListTasksParams.builder() - .contextId("context-diff-timestamps") - .tenant("tenant") - .pageSize(2) - .pageToken(result1.nextPageToken()) - .build(); - ListTasksResult result2 = taskStore.list(params2); - - assertEquals(5, result2.totalSize()); - assertEquals(2, result2.pageSize()); - assertNotNull(result2.nextPageToken(), "Should have next page token"); - - // Verify second page order (tasks with same timestamp, sorted by ID) - assertEquals("task-diff-b", result2.tasks().get(0).id(), "Third task should be 5 min ago, ID 'b'"); - assertEquals("task-diff-c", result2.tasks().get(1).id(), "Fourth task should be 5 min ago, ID 'c'"); - - // Page 3: Get last task - ListTasksParams params3 = ListTasksParams.builder() - .contextId("context-diff-timestamps") - .tenant("tenant") - .pageSize(2) - .pageToken(result2.nextPageToken()) - .build(); - ListTasksResult result3 = taskStore.list(params3); - - assertEquals(5, result3.totalSize()); - assertEquals(1, result3.pageSize()); - assertNull(result3.nextPageToken(), "Last page should have no next page token"); - - // Verify last task - assertEquals("task-diff-a", result3.tasks().get(0).id(), "Last task should be oldest"); - - // Verify no duplicates across all pages - List allTaskIds = new ArrayList<>(); - allTaskIds.addAll(result1.tasks().stream().map(Task::id).toList()); - allTaskIds.addAll(result2.tasks().stream().map(Task::id).toList()); - allTaskIds.addAll(result3.tasks().stream().map(Task::id).toList()); - - assertEquals(5, allTaskIds.size(), "Should have exactly 5 tasks across all pages"); - assertEquals(5, allTaskIds.stream().distinct().count(), "Should have no duplicate tasks"); - } - - @Test - @Transactional - public void testListTasksHistoryLimiting() { - // Create messages for history - List longHistory = new ArrayList<>(); - for (int i = 1; i <= 10; i++) { - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("Message " + i))) - .messageId("msg-history-limit-" + i) - .build(); - longHistory.add(message); - } - - // Create task with long history - use unique context - Task task = Task.builder() - .id("task-history-limit-unique-1") - .contextId("context-history-limit-unique") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .history(longHistory) - .build(); - - taskStore.save(task, false); - - // List with historyLength=3 (should keep only last 3 messages) - filter by unique context - ListTasksParams params = ListTasksParams.builder() - .contextId("context-history-limit-unique") - .tenant("tenant") - .historyLength(3) - .build(); - ListTasksResult result = taskStore.list(params); - - assertEquals(1, result.tasks().size()); - Task retrieved = result.tasks().get(0); - assertEquals(3, retrieved.history().size()); - // Should have messages 8, 9, 10 (last 3) - assertEquals("msg-history-limit-8", retrieved.history().get(0).messageId()); - assertEquals("msg-history-limit-9", retrieved.history().get(1).messageId()); - assertEquals("msg-history-limit-10", retrieved.history().get(2).messageId()); - } - - @Test - @Transactional - public void testListTasksArtifactInclusion() { - // Create task with artifacts - use unique context - List artifacts = new ArrayList<>(); - Artifact artifact = Artifact.builder() - .artifactId("artifact-unique-1") - .name("test-artifact") - .parts(Collections.singletonList(new TextPart("Artifact content"))) - .build(); - artifacts.add(artifact); - - Task task = Task.builder() - .id("task-artifact-unique-1") - .contextId("context-artifact-unique") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .artifacts(artifacts) - .build(); - - taskStore.save(task, false); - - // List without artifacts (default) - filter by unique context - ListTasksParams paramsWithoutArtifacts = ListTasksParams.builder() - .contextId("context-artifact-unique") - .tenant("tenant") - .build(); - ListTasksResult resultWithout = taskStore.list(paramsWithoutArtifacts); - - assertEquals(1, resultWithout.tasks().size()); - assertTrue(resultWithout.tasks().get(0).artifacts().isEmpty(), - "By default, artifacts should be excluded"); - - // List with artifacts - filter by unique context - ListTasksParams paramsWithArtifacts = ListTasksParams.builder() - .contextId("context-artifact-unique") - .tenant("tenant") - .includeArtifacts(true) - .build(); - ListTasksResult resultWith = taskStore.list(paramsWithArtifacts); - - assertEquals(1, resultWith.tasks().size()); - assertEquals(1, resultWith.tasks().get(0).artifacts().size(), - "When includeArtifacts=true, artifacts should be included"); - assertEquals("artifact-unique-1", resultWith.tasks().get(0).artifacts().get(0).artifactId()); - } - - @Test - @Transactional - public void testListTasksDefaultPageSize() { - // Create 100 tasks (more than default page size of 50) - for (int i = 1; i <= 100; i++) { - Task task = Task.builder() - .id("task-default-pagesize-" + String.format("%03d", i)) - .contextId("context-default-pagesize") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - taskStore.save(task, false); - } - - // List without specifying pageSize (should use default of 50) - ListTasksParams params = ListTasksParams.builder() - .contextId("context-default-pagesize") - .tenant("tenant") - .build(); - ListTasksResult result = taskStore.list(params); - - assertEquals(100, result.totalSize()); - assertEquals(50, result.pageSize(), "Default page size should be 50"); - assertNotNull(result.nextPageToken(), "Should have next page"); - } - - @Test - @Transactional - public void testListTasksInvalidPageTokenFormat() { - // Create a task - Task task = Task.builder() - .id("task-invalid-token") - .contextId("context-invalid-token") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - taskStore.save(task, false); - - // Test 1: Legacy ID-only pageToken should throw InvalidParamsError - ListTasksParams params1 = ListTasksParams.builder() - .contextId("context-invalid-token") - .tenant("tenant") - .pageToken("task-invalid-token") // ID-only format (legacy) - .build(); - - try { - taskStore.list(params1); - throw new AssertionError("Expected InvalidParamsError for legacy ID-only pageToken"); - } catch (io.a2a.spec.InvalidParamsError e) { - // Expected - legacy format not supported - assertTrue(e.getMessage().contains("Invalid pageToken format"), - "Error message should mention invalid format"); - } - - // Test 2: Malformed timestamp in pageToken should throw InvalidParamsError - ListTasksParams params2 = ListTasksParams.builder() - .contextId("context-invalid-token") - .tenant("tenant") - .pageToken("not-a-number:task-id") // Invalid timestamp - .build(); - - try { - taskStore.list(params2); - throw new AssertionError("Expected InvalidParamsError for malformed timestamp"); - } catch (io.a2a.spec.InvalidParamsError e) { - // Expected - malformed timestamp - assertTrue(e.getMessage().contains("timestamp must be numeric"), - "Error message should mention numeric timestamp requirement"); - } - } - - - @Test - @Transactional - public void testListTasksOrderingById() { - // Create tasks with same timestamp to test ID-based tie-breaking - // (spec requires sorting by timestamp DESC, then ID ASC) - OffsetDateTime sameTimestamp = OffsetDateTime.now(java.time.ZoneOffset.UTC); - - Task task1 = Task.builder() - .id("task-order-a") - .contextId("context-order") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) - .build(); - - Task task2 = Task.builder() - .id("task-order-b") - .contextId("context-order") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) - .build(); - - Task task3 = Task.builder() - .id("task-order-c") - .contextId("context-order") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, null, sameTimestamp)) - .build(); - - // Save in reverse order - taskStore.save(task3, false); - taskStore.save(task1, false); - taskStore.save(task2, false); - - // List should return sorted by timestamp DESC (all same), then by ID ASC - ListTasksParams params = ListTasksParams.builder() - .contextId("context-order") - .tenant("tenant") - .build(); - ListTasksResult result = taskStore.list(params); - - assertEquals(3, result.tasks().size()); - assertEquals("task-order-a", result.tasks().get(0).id()); - assertEquals("task-order-b", result.tasks().get(1).id()); - assertEquals("task-order-c", result.tasks().get(2).id()); - } -} diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java deleted file mode 100644 index 00c055801..000000000 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentCardProducer.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.a2a.extras.taskstore.database.jpa; - -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.AgentInterface; -import io.a2a.spec.TransportProtocol; -import io.quarkus.arc.profile.IfBuildProfile; - -/** - * Simple test AgentCard producer for our integration test. - */ -@ApplicationScoped -@IfBuildProfile("test") -public class JpaDatabaseTaskStoreTestAgentCardProducer { - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - return AgentCard.builder() - .name("JPA TaskStore Integration Test Agent") - .description("Test agent for verifying JPA TaskStore integration") - .version("1.0.0") - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .capabilities(AgentCapabilities.builder().build()) - .skills(List.of()) - .supportedInterfaces(Collections.singletonList( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:8081") - )) - .build(); - } -} diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java deleted file mode 100644 index fd530a761..000000000 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.a2a.extras.taskstore.database.jpa; - -import java.util.List; - -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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import io.quarkus.arc.profile.IfBuildProfile; - -/** - * Simple test AgentExecutor that responds to messages and uses AgentEmitter.addArtifact() - * to trigger TaskUpdateEvents for our integration test. - */ -@IfBuildProfile("test") -@ApplicationScoped -public class JpaDatabaseTaskStoreTestAgentExecutor { - - @Produces - public AgentExecutor agentExecutor() { - return new AgentExecutor() { - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - System.out.println("TestAgentExecutor.execute() called for task: " + context.getTaskId()); - System.out.println("Message " + context.getMessage()); - String lastText = getLastTextPart(context.getMessage()); - switch (lastText) { - case "create": - agentEmitter.submit(); - break; - case "add-artifact": - agentEmitter.addArtifact(List.of(new TextPart(lastText)), "art-1", "test", null); - break; - default: - throw new InvalidRequestError(lastText + " is unknown"); - } - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - agentEmitter.cancel(); - } - }; - } - - private String getLastTextPart(Message message) throws A2AError { - Part part = message.parts().get(message.parts().size() - 1); - if (part instanceof TextPart) { - return ((TextPart) part).text(); - } - throw new InvalidRequestError("No parts"); - } -} diff --git a/extras/task-store-database-jpa/src/test/resources/META-INF/persistence.xml b/extras/task-store-database-jpa/src/test/resources/META-INF/persistence.xml deleted file mode 100644 index e80e61c86..000000000 --- a/extras/task-store-database-jpa/src/test/resources/META-INF/persistence.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - A2A Java SDK JPA TaskStore Test Configuration - - - io.a2a.extras.taskstore.database.jpa.JpaTask - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/extras/task-store-database-jpa/src/test/resources/application.properties b/extras/task-store-database-jpa/src/test/resources/application.properties deleted file mode 100644 index 1d1592ad9..000000000 --- a/extras/task-store-database-jpa/src/test/resources/application.properties +++ /dev/null @@ -1,11 +0,0 @@ -# Test configuration for JPA TaskStore -# H2 in-memory database for testing -quarkus.datasource.db-kind=h2 -quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -quarkus.datasource.username=sa -quarkus.datasource.password= - -# Hibernate configuration -quarkus.hibernate-orm.database.generation=drop-and-create -quarkus.hibernate-orm.log.sql=true -quarkus.hibernate-orm.log.format-sql=true diff --git a/http-client/pom.xml b/http-client/pom.xml deleted file mode 100644 index 394ab2a0d..000000000 --- a/http-client/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - a2a-java-sdk-http-client - - jar - - Java SDK A2A HTTP Client - Java SDK for the Agent2Agent Protocol (A2A) - HTTP Client - - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-spec-grpc - - - com.google.protobuf - protobuf-java-util - - - - org.junit.jupiter - junit-jupiter-api - test - - - - org.mock-server - mockserver-netty - test - - - - \ No newline at end of file diff --git a/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java b/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java deleted file mode 100644 index b4847cd40..000000000 --- a/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java +++ /dev/null @@ -1,144 +0,0 @@ -package io.a2a.client.http; - - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; - -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientJSONError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.A2AError; -import org.jspecify.annotations.Nullable; - -import static io.a2a.util.Assert.checkNotNullParam; - -import io.a2a.spec.AgentInterface; - -public class A2ACardResolver { - private final A2AHttpClient httpClient; - private final String url; - private final @Nullable Map authHeaders; - - private static final String DEFAULT_AGENT_CARD_PATH = "/.well-known/agent-card.json"; - - /** - * Get the agent card for an A2A agent. An HTTP client will be auto-selected via {@link A2AHttpClientFactory}. - * - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if baseUrl is null - */ - public A2ACardResolver(String baseUrl) throws A2AClientError { - this(A2AHttpClientFactory.create(), baseUrl, null, null); - } - - /** - * Get the agent card for an A2A agent. An HTTP client will be auto-selected via {@link A2AHttpClientFactory}. - * - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if baseUrl is null - */ - public A2ACardResolver(String baseUrl, @Nullable String tenant) throws A2AClientError { - this(A2AHttpClientFactory.create(), baseUrl, tenant, null); - } - - /** - * Constructs an A2ACardResolver with a specific HTTP client and base URL. - * - * @param httpClient the HTTP client to use for fetching the agent card, must not be null - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if httpClient or baseUrl is null - */ - public A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable String tenant) throws A2AClientError { - this(httpClient, baseUrl, tenant, null); - } - - /** - * Constructs an A2ACardResolver with a specific HTTP client, base URL, and custom agent card path. - * - * @param httpClient the HTTP client to use for fetching the agent card, must not be null - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @param agentCardPath optional path to the agent card endpoint relative to the base - * agent URL, defaults to "/.well-known/agent-card.json" if null or empty - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if httpClient or baseUrl is null - */ - public A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable String tenant, @Nullable String agentCardPath) throws A2AClientError { - this(httpClient, baseUrl, tenant, agentCardPath, null); - } - - /** - * Constructs an A2ACardResolver with full configuration including authentication headers. - * - * @param httpClient the HTTP client to use for fetching the agent card, must not be null - * @param baseUrl the base URL for the agent whose agent card we want to retrieve, must not be null - * @param tenant the tenant path to use when fetching the agent card, may be null for no tenant - * @param agentCardPath optional path to the agent card endpoint relative to the base - * agent URL, defaults to "/.well-known/agent-card.json" if null or empty - * @param authHeaders the HTTP authentication headers to use, may be null - * @throws A2AClientError if the URL for the agent is invalid - * @throws IllegalArgumentException if httpClient or baseUrl is null - */ - public A2ACardResolver(A2AHttpClient httpClient, String baseUrl, @Nullable String tenant, @Nullable String agentCardPath, - @Nullable Map authHeaders) throws A2AClientError { - checkNotNullParam("httpClient", httpClient); - checkNotNullParam("baseUrl", baseUrl); - - this.httpClient = httpClient; - String effectiveAgentCardPath = (agentCardPath == null || agentCardPath.isEmpty()) ? DEFAULT_AGENT_CARD_PATH : agentCardPath; - try { - this.url = new URI(io.a2a.util.Utils.buildBaseUrl(new AgentInterface("JSONRPC", baseUrl, ""), tenant)).resolve(effectiveAgentCardPath).toString(); - } catch (URISyntaxException e) { - throw new A2AClientError("Invalid agent URL", e); - } - this.authHeaders = authHeaders; - } - - /** - * Get the agent card for the configured A2A agent. - * - * @return the agent card - * @throws A2AClientError If an HTTP error occurs fetching the card - * @throws A2AClientJSONError If the response body cannot be decoded as JSON or validated against the AgentCard schema - */ - public AgentCard getAgentCard() throws A2AClientError, A2AClientJSONError { - A2AHttpClient.GetBuilder builder = httpClient.createGet() - .url(url) - .addHeader("Content-Type", "application/json"); - - if (authHeaders != null) { - for (Map.Entry entry : authHeaders.entrySet()) { - builder.addHeader(entry.getKey(), entry.getValue()); - } - } - - String body; - try { - A2AHttpResponse response = builder.get(); - if (!response.success()) { - throw new A2AClientError("Failed to obtain agent card: " + response.status()); - } - body = response.body(); - } catch (IOException | InterruptedException e) { - throw new A2AClientError("Failed to obtain agent card", e); - } - - try { - io.a2a.grpc.AgentCard.Builder agentCardBuilder = io.a2a.grpc.AgentCard.newBuilder(); - JSONRPCUtils.parseJsonString(body, agentCardBuilder, ""); - return ProtoUtils.FromProto.agentCard(agentCardBuilder); - } catch (A2AError | JsonProcessingException e) { - throw new A2AClientJSONError("Could not unmarshal agent card response", e); - } - } -} diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java b/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java deleted file mode 100644 index 9e4f5f705..000000000 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpClient.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.a2a.client.http; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -public interface A2AHttpClient { - - String CONTENT_TYPE= "Content-Type"; - String APPLICATION_JSON= "application/json"; - String ACCEPT = "Accept"; - String EVENT_STREAM = "text/event-stream"; - - GetBuilder createGet(); - - PostBuilder createPost(); - - DeleteBuilder createDelete(); - - interface Builder> { - T url(String s); - T addHeaders(Map headers); - T addHeader(String name, String value); - } - - interface GetBuilder extends Builder { - A2AHttpResponse get() throws IOException, InterruptedException; - CompletableFuture getAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException; - } - - interface PostBuilder extends Builder { - PostBuilder body(String body); - A2AHttpResponse post() throws IOException, InterruptedException; - CompletableFuture postAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException; - } - - interface DeleteBuilder extends Builder { - A2AHttpResponse delete() throws IOException, InterruptedException; - } -} diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientFactory.java b/http-client/src/main/java/io/a2a/client/http/A2AHttpClientFactory.java deleted file mode 100644 index 05bac3112..000000000 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientFactory.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.a2a.client.http; - -import java.util.Comparator; -import java.util.ServiceLoader; -import java.util.stream.StreamSupport; - -/** - * Factory for creating {@link A2AHttpClient} instances using the ServiceLoader mechanism. - * - *

- * This factory discovers available {@link A2AHttpClientProvider} implementations at runtime - * and selects the one with the highest priority. If no providers are found, it falls back - * to creating a {@link JdkA2AHttpClient}. - * - *

Usage

- *
{@code
- * // Get the default client (highest priority provider)
- * A2AHttpClient client = A2AHttpClientFactory.create();
- *
- * // Use with try-with-resources if the client implements AutoCloseable
- * try (A2AHttpClient client = A2AHttpClientFactory.create()) {
- *     A2AHttpResponse response = client.createGet()
- *         .url("https://example.com")
- *         .get();
- * }
- * }
- * - *

Priority System

- *

- * Providers are selected based on their priority value (higher is better): - *

    - *
  • JdkA2AHttpClient: priority 0 (fallback)
  • - *
  • VertxA2AHttpClient: priority 100 (preferred when available)
  • - *
- * - *

Custom Providers

- *

- * To add a custom provider, implement {@link A2AHttpClientProvider} and register it - * in {@code META-INF/services/io.a2a.client.http.A2AHttpClientProvider}. - */ -public final class A2AHttpClientFactory { - - private A2AHttpClientFactory() { - // Utility class - } - - /** - * Creates a new A2AHttpClient instance using the highest priority provider available. - * - *

- * This method uses the ServiceLoader mechanism to discover providers at runtime. - * If no providers are found, it falls back to creating a {@link JdkA2AHttpClient}. - * - * @return a new A2AHttpClient instance - */ - public static A2AHttpClient create() { - ServiceLoader loader = ServiceLoader.load(A2AHttpClientProvider.class); - - return StreamSupport.stream(loader.spliterator(), false) - .max(Comparator.comparingInt(A2AHttpClientProvider::priority)) - .map(A2AHttpClientProvider::create) - .orElseGet(JdkA2AHttpClient::new); - } - - /** - * Creates a new A2AHttpClient instance using a specific provider by name. - * - *

- * This method is useful for testing or when you need to force a specific implementation. - * - * @param providerName the name of the provider to use - * @return a new A2AHttpClient instance from the specified provider - * @throws IllegalArgumentException if no provider with the given name is found - */ - public static A2AHttpClient create(String providerName) { - if (providerName == null || providerName.isEmpty()) { - throw new IllegalArgumentException("Provider name must not be null or empty"); - } - - ServiceLoader loader = ServiceLoader.load(A2AHttpClientProvider.class); - - return StreamSupport.stream(loader.spliterator(), false) - .filter(provider -> providerName.equals(provider.name())) - .findFirst() - .map(A2AHttpClientProvider::create) - .orElseThrow(() -> new IllegalArgumentException( - "No A2AHttpClientProvider found with name: " + providerName)); - } -} diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientProvider.java b/http-client/src/main/java/io/a2a/client/http/A2AHttpClientProvider.java deleted file mode 100644 index 8c33c66e6..000000000 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpClientProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.a2a.client.http; - -/** - * Service provider interface for creating {@link A2AHttpClient} instances. - * - *

- * Implementations of this interface can be registered via the Java ServiceLoader - * mechanism. The {@link A2AHttpClientFactory} will discover and use the highest - * priority provider available. - * - *

- * To register a provider, create a file named - * {@code META-INF/services/io.a2a.client.http.A2AHttpClientProvider} containing - * the fully qualified class name of your provider implementation. - */ -public interface A2AHttpClientProvider { - - /** - * Creates a new instance of an A2AHttpClient. - * - * @return a new A2AHttpClient instance - */ - A2AHttpClient create(); - - /** - * Returns the priority of this provider. Higher priority providers are - * preferred over lower priority ones. - * - *

- * Default priorities: - *

    - *
  • JdkA2AHttpClient: 0 (fallback)
  • - *
  • VertxA2AHttpClient: 100 (preferred when available)
  • - *
- * - * @return the priority value (higher is better) - */ - default int priority() { - return 0; - } - - /** - * Returns the name of this provider for logging and debugging purposes. - * - * @return the provider name - */ - String name(); -} diff --git a/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java b/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java deleted file mode 100644 index 171fceebd..000000000 --- a/http-client/src/main/java/io/a2a/client/http/A2AHttpResponse.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.a2a.client.http; - -public interface A2AHttpResponse { - int status(); - - boolean success(); - - String body(); -} diff --git a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java b/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java deleted file mode 100644 index d5bc68651..000000000 --- a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClient.java +++ /dev/null @@ -1,311 +0,0 @@ -package io.a2a.client.http; - -import static java.net.HttpURLConnection.HTTP_FORBIDDEN; -import static java.net.HttpURLConnection.HTTP_MULT_CHOICE; -import static java.net.HttpURLConnection.HTTP_OK; -import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; - -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.http.HttpResponse.BodyHandler; -import java.net.http.HttpResponse.BodyHandlers; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Flow; -import java.util.function.Consumer; -import org.jspecify.annotations.Nullable; - -import io.a2a.common.A2AErrorMessages; - -public class JdkA2AHttpClient implements A2AHttpClient { - - private final HttpClient httpClient; - - public JdkA2AHttpClient() { - httpClient = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .followRedirects(HttpClient.Redirect.NORMAL) - .build(); - } - - @Override - public GetBuilder createGet() { - return new JdkGetBuilder(); - } - - @Override - public PostBuilder createPost() { - return new JdkPostBuilder(); - } - - @Override - public DeleteBuilder createDelete() { - return new JdkDeleteBuilder(); - } - - private abstract class JdkBuilder> implements Builder { - private String url = ""; - private Map headers = new HashMap<>(); - - @Override - public T url(String url) { - this.url = url; - return self(); - } - - @Override - public T addHeader(String name, String value) { - headers.put(name, value); - return self(); - } - - @Override - public T addHeaders(Map headers) { - if(headers != null && ! headers.isEmpty()) { - for (Map.Entry entry : headers.entrySet()) { - addHeader(entry.getKey(), entry.getValue()); - } - } - return self(); - } - - @SuppressWarnings("unchecked") - T self() { - return (T) this; - } - - protected HttpRequest.Builder createRequestBuilder() throws IOException { - HttpRequest.Builder builder = HttpRequest.newBuilder() - .uri(URI.create(url)); - for (Map.Entry headerEntry : headers.entrySet()) { - builder.header(headerEntry.getKey(), headerEntry.getValue()); - } - return builder; - } - - protected CompletableFuture asyncRequest( - HttpRequest request, - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable - ) { - Flow.Subscriber subscriber = new Flow.Subscriber() { - private Flow.@Nullable Subscription subscription; - private volatile boolean errorRaised = false; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - this.subscription.request(1); - } - - @Override - public void onNext(String item) { - // SSE messages sometimes start with "data:". Strip that off - if (item != null && item.startsWith("data:")) { - item = item.substring(5).trim(); - if (!item.isEmpty()) { - messageConsumer.accept(item); - } - } - if (subscription != null) { - subscription.request(1); - } - } - - @Override - public void onError(Throwable throwable) { - if (!errorRaised) { - errorRaised = true; - errorConsumer.accept(throwable); - } - if (subscription != null) { - subscription.cancel(); - } - } - - @Override - public void onComplete() { - if (!errorRaised) { - completeRunnable.run(); - } - if (subscription != null) { - subscription.cancel(); - } - } - }; - - // Create a custom body handler that checks status before processing body - BodyHandler bodyHandler = responseInfo -> { - // Check for authentication/authorization errors only - if (responseInfo.statusCode() == HTTP_UNAUTHORIZED || responseInfo.statusCode() == HTTP_FORBIDDEN) { - final String errorMessage; - if (responseInfo.statusCode() == HTTP_UNAUTHORIZED) { - errorMessage = A2AErrorMessages.AUTHENTICATION_FAILED; - } else { - errorMessage = A2AErrorMessages.AUTHORIZATION_FAILED; - } - // Return a body subscriber that immediately signals error - return BodySubscribers.fromSubscriber(new Flow.Subscriber>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscriber.onError(new IOException(errorMessage)); - } - - @Override - public void onNext(List item) { - // Should not be called - } - - @Override - public void onError(Throwable throwable) { - // Should not be called - } - - @Override - public void onComplete() { - // Should not be called - } - }); - } else { - // For all other status codes (including other errors), proceed with normal line subscriber - return BodyHandlers.fromLineSubscriber(subscriber).apply(responseInfo); - } - }; - - // Send the response async, and let the subscriber handle the lines. - return httpClient.sendAsync(request, bodyHandler) - .thenAccept(response -> { - // Handle non-authentication/non-authorization errors here - if (!isSuccessStatus(response.statusCode()) && - response.statusCode() != HTTP_UNAUTHORIZED && - response.statusCode() != HTTP_FORBIDDEN) { - subscriber.onError(new IOException("Request failed with status " + response.statusCode() + ":" + response.body())); - } - }); - } - } - - private class JdkGetBuilder extends JdkBuilder implements A2AHttpClient.GetBuilder { - - private HttpRequest.Builder createRequestBuilder(boolean SSE) throws IOException { - HttpRequest.Builder builder = super.createRequestBuilder().GET(); - if (SSE) { - builder.header(ACCEPT, EVENT_STREAM); - } - return builder; - } - - @Override - public A2AHttpResponse get() throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(false) - .build(); - HttpResponse response = - httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); - return new JdkHttpResponse(response); - } - - @Override - public CompletableFuture getAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(true) - .build(); - return super.asyncRequest(request, messageConsumer, errorConsumer, completeRunnable); - } - - } - - private class JdkDeleteBuilder extends JdkBuilder implements A2AHttpClient.DeleteBuilder { - - @Override - public A2AHttpResponse delete() throws IOException, InterruptedException { - HttpRequest request = super.createRequestBuilder().DELETE().build(); - HttpResponse response = - httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); - return new JdkHttpResponse(response); - } - - } - - private class JdkPostBuilder extends JdkBuilder implements A2AHttpClient.PostBuilder { - String body = ""; - - @Override - public PostBuilder body(String body) { - this.body = body; - return self(); - } - - private HttpRequest.Builder createRequestBuilder(boolean SSE) throws IOException { - HttpRequest.Builder builder = super.createRequestBuilder() - .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)); - if (SSE) { - builder.header(ACCEPT, EVENT_STREAM); - } - return builder; - } - - @Override - public A2AHttpResponse post() throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(false) - .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)) - .build(); - HttpResponse response = - httpClient.send(request, BodyHandlers.ofString(StandardCharsets.UTF_8)); - - if (response.statusCode() == HTTP_UNAUTHORIZED) { - throw new IOException(A2AErrorMessages.AUTHENTICATION_FAILED); - } else if (response.statusCode() == HTTP_FORBIDDEN) { - throw new IOException(A2AErrorMessages.AUTHORIZATION_FAILED); - } - - return new JdkHttpResponse(response); - } - - @Override - public CompletableFuture postAsyncSSE( - Consumer messageConsumer, - Consumer errorConsumer, - Runnable completeRunnable) throws IOException, InterruptedException { - HttpRequest request = createRequestBuilder(true) - .build(); - return super.asyncRequest(request, messageConsumer, errorConsumer, completeRunnable); - } - } - - private record JdkHttpResponse(HttpResponse response) implements A2AHttpResponse { - - @Override - public int status() { - return response.statusCode(); - } - - @Override - public boolean success() {// Send the request and get the response - return success(response); - } - - static boolean success(HttpResponse response) { - return response.statusCode() >= HTTP_OK && response.statusCode() < HTTP_MULT_CHOICE; - } - - @Override - public String body() { - return response.body(); - } - } - - private static boolean isSuccessStatus(int statusCode) { - return statusCode >= HTTP_OK && statusCode < HTTP_MULT_CHOICE; - } -} diff --git a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClientProvider.java b/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClientProvider.java deleted file mode 100644 index 1bf388286..000000000 --- a/http-client/src/main/java/io/a2a/client/http/JdkA2AHttpClientProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.a2a.client.http; - -/** - * Service provider for {@link JdkA2AHttpClient}. - * - *

- * This provider has the lowest priority (0) and serves as the fallback implementation - * when no other providers are available. The JDK HTTP client is always available as it - * uses only standard Java libraries. - */ -public final class JdkA2AHttpClientProvider implements A2AHttpClientProvider { - - @Override - public A2AHttpClient create() { - return new JdkA2AHttpClient(); - } - - @Override - public int priority() { - return 0; // Lowest priority - fallback - } - - @Override - public String name() { - return "jdk"; - } -} diff --git a/http-client/src/main/java/io/a2a/client/http/package-info.java b/http-client/src/main/java/io/a2a/client/http/package-info.java deleted file mode 100644 index 525333cf1..000000000 --- a/http-client/src/main/java/io/a2a/client/http/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.client.http; - -import org.jspecify.annotations.NullMarked; - diff --git a/http-client/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider b/http-client/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider deleted file mode 100644 index 78dbb361e..000000000 --- a/http-client/src/main/resources/META-INF/services/io.a2a.client.http.A2AHttpClientProvider +++ /dev/null @@ -1 +0,0 @@ -io.a2a.client.http.JdkA2AHttpClientProvider diff --git a/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java b/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java deleted file mode 100644 index 3254992ef..000000000 --- a/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java +++ /dev/null @@ -1,191 +0,0 @@ -package io.a2a.client.http; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.util.JsonFormat; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.spec.A2AClientError; -import io.a2a.spec.A2AClientJSONError; -import io.a2a.spec.AgentCard; -import java.util.Map; -import org.junit.jupiter.api.Test; - -public class A2ACardResolverTest { - - private static final String AGENT_CARD_PATH = "/.well-known/agent-card.json"; - - @Test - public void testConstructorStripsSlashes() throws Exception { - TestHttpClient client = new TestHttpClient(); - client.body = JsonMessages.AGENT_CARD; - - A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", ""); - AgentCard card = resolver.getAgentCard(); - - assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); - - - resolver = new A2ACardResolver(client, "http://example.com", ""); - card = resolver.getAgentCard(); - - assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); - - // baseUrl with trailing slash, agentCardParth with leading slash - resolver = new A2ACardResolver(client, "http://example.com/", AGENT_CARD_PATH); - card = resolver.getAgentCard(); - - assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); - - // baseUrl without trailing slash, agentCardPath with leading slash - resolver = new A2ACardResolver(client, "http://example.com", AGENT_CARD_PATH); - card = resolver.getAgentCard(); - - assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); - - // baseUrl with trailing slash, agentCardPath without leading slash - resolver = new A2ACardResolver(client, "http://example.com/", AGENT_CARD_PATH.substring(1)); - card = resolver.getAgentCard(); - - assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); - - // baseUrl without trailing slash, agentCardPath without leading slash - resolver = new A2ACardResolver(client, "http://example.com", AGENT_CARD_PATH.substring(1)); - card = resolver.getAgentCard(); - - assertEquals("http://example.com" + AGENT_CARD_PATH, client.url); - } - - - @Test - public void testGetAgentCardSuccess() throws Exception { - TestHttpClient client = new TestHttpClient(); - client.body = JsonMessages.AGENT_CARD; - - A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", ""); - AgentCard card = resolver.getAgentCard(); - - AgentCard expectedCard = unmarshalFrom(JsonMessages.AGENT_CARD); - String expected = printAgentCard(expectedCard); - - String requestCardString = printAgentCard(card); - assertEquals(expected, requestCardString); - } - - private AgentCard unmarshalFrom(String body) throws JsonProcessingException { - io.a2a.grpc.AgentCard.Builder agentCardBuilder = io.a2a.grpc.AgentCard.newBuilder(); - JSONRPCUtils.parseJsonString(body, agentCardBuilder, ""); - return ProtoUtils.FromProto.agentCard(agentCardBuilder); - } - - private String printAgentCard(AgentCard agentCard) throws InvalidProtocolBufferException { - return JsonFormat.printer().print(ProtoUtils.ToProto.agentCard(agentCard)); - } - - @Test - public void testGetAgentCardJsonDecodeError() throws Exception { - TestHttpClient client = new TestHttpClient(); - client.body = "X" + JsonMessages.AGENT_CARD; - - A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", ""); - - boolean success = false; - try { - AgentCard card = resolver.getAgentCard(); - success = true; - } catch (A2AClientJSONError expected) { - } - assertFalse(success); - } - - - @Test - public void testGetAgentCardRequestError() throws Exception { - TestHttpClient client = new TestHttpClient(); - client.status = 503; - - A2ACardResolver resolver = new A2ACardResolver(client, "http://example.com/", ""); - - String msg = null; - try { - AgentCard card = resolver.getAgentCard(); - } catch (A2AClientError expected) { - msg = expected.getMessage(); - } - assertTrue(msg.contains("503")); - } - - private static class TestHttpClient implements A2AHttpClient { - int status = 200; - String body; - String url; - - @Override - public GetBuilder createGet() { - return new TestGetBuilder(); - } - - @Override - public PostBuilder createPost() { - return null; - } - - @Override - public DeleteBuilder createDelete() { - return null; - } - - class TestGetBuilder implements A2AHttpClient.GetBuilder { - - @Override - public A2AHttpResponse get() throws IOException, InterruptedException { - return new A2AHttpResponse() { - @Override - public int status() { - return status; - } - - @Override - public boolean success() { - return status == 200; - } - - @Override - public String body() { - return body; - } - }; - } - - @Override - public CompletableFuture getAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { - return null; - } - - @Override - public GetBuilder url(String s) { - url = s; - return this; - } - - @Override - public GetBuilder addHeader(String name, String value) { - return this; - } - - @Override - public GetBuilder addHeaders(Map headers) { - return this; - } - } - } - -} diff --git a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryTest.java b/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryTest.java deleted file mode 100644 index 72de52230..000000000 --- a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package io.a2a.client.http; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.Test; - -public class A2AHttpClientFactoryTest { - - @Test - public void testCreateReturnsNonNull() { - A2AHttpClient client = A2AHttpClientFactory.create(); - assertNotNull(client, "Factory should return a non-null client"); - } - - @Test - public void testCreateReturnsJdkClient() { - // When Vertx is not on classpath, JDK client should be used - A2AHttpClient client = A2AHttpClientFactory.create(); - assertNotNull(client); - assertInstanceOf(JdkA2AHttpClient.class, client, - "Factory should return JdkA2AHttpClient when Vertx is not available"); - } - - @Test - public void testCreateWithJdkProviderName() { - A2AHttpClient client = A2AHttpClientFactory.create("jdk"); - assertNotNull(client); - assertInstanceOf(JdkA2AHttpClient.class, client, - "Factory should return JdkA2AHttpClient when 'jdk' provider is requested"); - } - - @Test - public void testCreateWithVertxProviderNameThrows() { - // Vertx provider is not available in the core module - IllegalArgumentException exception = assertThrows( - IllegalArgumentException.class, - () -> A2AHttpClientFactory.create("vertx"), - "Factory should throw IllegalArgumentException when vertx provider is not found" - ); - assertTrue(exception.getMessage().contains("vertx"), - "Exception message should mention the provider name"); - } - - @Test - public void testCreateWithInvalidProviderNameThrows() { - IllegalArgumentException exception = assertThrows( - IllegalArgumentException.class, - () -> A2AHttpClientFactory.create("nonexistent"), - "Factory should throw IllegalArgumentException for unknown provider" - ); - assertTrue(exception.getMessage().contains("nonexistent"), - "Exception message should mention the provider name"); - } - - @Test - public void testCreateWithNullProviderNameThrows() { - assertThrows( - IllegalArgumentException.class, - () -> A2AHttpClientFactory.create(null), - "Factory should throw IllegalArgumentException for null provider name" - ); - } - - @Test - public void testCreateWithEmptyProviderNameThrows() { - assertThrows( - IllegalArgumentException.class, - () -> A2AHttpClientFactory.create(""), - "Factory should throw IllegalArgumentException for empty provider name" - ); - } - - @Test - public void testCreatedClientIsUsable() { - A2AHttpClient client = A2AHttpClientFactory.create(); - assertNotNull(client); - - // Verify we can create builders - A2AHttpClient.GetBuilder getBuilder = client.createGet(); - assertNotNull(getBuilder, "Should be able to create GET builder"); - - A2AHttpClient.PostBuilder postBuilder = client.createPost(); - assertNotNull(postBuilder, "Should be able to create POST builder"); - - A2AHttpClient.DeleteBuilder deleteBuilder = client.createDelete(); - assertNotNull(deleteBuilder, "Should be able to create DELETE builder"); - } -} diff --git a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryUsageExample.java b/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryUsageExample.java deleted file mode 100644 index 86da8c8cf..000000000 --- a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientFactoryUsageExample.java +++ /dev/null @@ -1,122 +0,0 @@ -package io.a2a.client.http; - -import java.io.IOException; - -/** - * Example demonstrating how to use {@link A2AHttpClientFactory} to obtain HTTP client instances. - * - *

- * This class shows various usage patterns for the factory-based approach to creating - * A2AHttpClient instances. - */ -public class A2AHttpClientFactoryUsageExample { - - /** - * Example 1: Basic usage with automatic selection of best available client. - */ - public void basicUsage() throws IOException, InterruptedException { - // The factory automatically selects the best available implementation: - // - VertxA2AHttpClient (priority 100) if Vert.x is on the classpath - // - JdkA2AHttpClient (priority 0) as fallback - A2AHttpClient client = A2AHttpClientFactory.create(); - - try { - A2AHttpResponse response = client.createGet() - .url("https://api.example.com/data") - .addHeader("Accept", "application/json") - .get(); - - if (response.success()) { - System.out.println("Response: " + response.body()); - } - } finally { - // Close if the client supports AutoCloseable (Vertx does, JDK doesn't) - if (client instanceof AutoCloseable) { - try { - ((AutoCloseable) client).close(); - } catch (Exception e) { - // Handle close exception - } - } - } - } - - /** - * Example 2: Try-with-resources pattern (recommended for AutoCloseable clients). - */ - public void tryWithResourcesUsage() throws Exception { - A2AHttpClient client = A2AHttpClientFactory.create(); - - // Only use try-with-resources if the client is AutoCloseable - if (client instanceof AutoCloseable) { - try (AutoCloseable closeableClient = (AutoCloseable) client) { - A2AHttpResponse response = client.createPost() - .url("https://api.example.com/submit") - .addHeader("Content-Type", "application/json") - .body("{\"key\":\"value\"}") - .post(); - - System.out.println("Status: " + response.status()); - } - } else { - // Non-closeable client, use normally - A2AHttpResponse response = client.createPost() - .url("https://api.example.com/submit") - .addHeader("Content-Type", "application/json") - .body("{\"key\":\"value\"}") - .post(); - - System.out.println("Status: " + response.status()); - } - } - - /** - * Example 3: Explicitly selecting a specific implementation. - */ - public void specificProviderUsage() throws IOException, InterruptedException { - // Force the use of JDK client even if Vert.x is available - A2AHttpClient jdkClient = A2AHttpClientFactory.create("jdk"); - A2AHttpResponse response = jdkClient.createGet() - .url("https://api.example.com/data") - .get(); - - System.out.println("Using JDK client: " + response.status()); - - // Or explicitly use Vert.x client - try (AutoCloseable vertxClient = (AutoCloseable) A2AHttpClientFactory.create("vertx")) { - A2AHttpResponse vertxResponse = ((A2AHttpClient) vertxClient).createGet() - .url("https://api.example.com/data") - .get(); - - System.out.println("Using Vert.x client: " + vertxResponse.status()); - } catch (Exception e) { - // Handle exceptions - } - } - - /** - * Example 4: Defensive programming - handling unknown implementations. - */ - public void defensiveUsage() throws IOException, InterruptedException { - A2AHttpClient client = null; - try { - client = A2AHttpClientFactory.create(); - - A2AHttpResponse response = client.createGet() - .url("https://api.example.com/data") - .get(); - - System.out.println("Response: " + response.body()); - - } finally { - // Safely close if possible - if (client instanceof AutoCloseable) { - try { - ((AutoCloseable) client).close(); - } catch (Exception e) { - System.err.println("Warning: Failed to close client: " + e.getMessage()); - } - } - } - } -} diff --git a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientProviderTest.java b/http-client/src/test/java/io/a2a/client/http/A2AHttpClientProviderTest.java deleted file mode 100644 index b2e222517..000000000 --- a/http-client/src/test/java/io/a2a/client/http/A2AHttpClientProviderTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.a2a.client.http; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.Test; - -public class A2AHttpClientProviderTest { - - @Test - public void testJdkProviderCreatesClient() { - JdkA2AHttpClientProvider provider = new JdkA2AHttpClientProvider(); - A2AHttpClient client = provider.create(); - assertNotNull(client); - assertInstanceOf(JdkA2AHttpClient.class, client); - } - - @Test - public void testJdkProviderPriority() { - JdkA2AHttpClientProvider provider = new JdkA2AHttpClientProvider(); - assertEquals(0, provider.priority(), "JDK provider should have priority 0"); - } - - @Test - public void testJdkProviderName() { - JdkA2AHttpClientProvider provider = new JdkA2AHttpClientProvider(); - assertEquals("jdk", provider.name(), "JDK provider name should be 'jdk'"); - } -} diff --git a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java b/http-client/src/test/java/io/a2a/client/http/JsonMessages.java deleted file mode 100644 index 89d146787..000000000 --- a/http-client/src/test/java/io/a2a/client/http/JsonMessages.java +++ /dev/null @@ -1,81 +0,0 @@ -package io.a2a.client.http; - -/** - * Request and response messages used by the tests. These have been created following examples from - * the A2A sample messages. - */ -public class JsonMessages { - - static final String AGENT_CARD = """ - { - "name": "GeoSpatial Route Planner Agent", - "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", - "supportedInterfaces" : [ - {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "JSONRPC", "tenant": ""}, - {"url": "https://georoute-agent.example.com/a2a/grpc", "protocolBinding": "GRPC", "tenant": ""}, - {"url": "https://georoute-agent.example.com/a2a/json", "protocolBinding": "HTTP+JSON", "tenant": ""} - ], - "provider": { - "organization": "Example Geo Services Inc.", - "url": "https://www.examplegeoservices.com" - }, - "iconUrl": "https://georoute-agent.example.com/icon.png", - "version": "1.2.0", - "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", - "capabilities": { - "streaming": true, - "pushNotifications": true - }, - "securitySchemes": { - "google": { - "openIdConnectSecurityScheme": { - "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" - } - } - }, - "securityRequirements": [{ "schemes": { "google": { "list": ["openid", "profile", "email"] } } }], - "defaultInputModes": ["application/json", "text/plain"], - "defaultOutputModes": ["application/json", "image/png"], - "skills": [ - { - "id": "route-optimizer-traffic", - "name": "Traffic-Aware Route Optimizer", - "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", - "tags": ["maps", "routing", "navigation", "directions", "traffic"], - "examples": [ - "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", - "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" - ], - "inputModes": ["application/json", "text/plain"], - "outputModes": [ - "application/json", - "application/vnd.geo+json", - "text/html" - ] - }, - { - "id": "custom-map-generator", - "name": "Personalized Map Generator", - "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", - "tags": ["maps", "customization", "visualization", "cartography"], - "examples": [ - "Generate a map of my upcoming road trip with all planned stops highlighted.", - "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." - ], - "inputModes": ["application/json"], - "outputModes": [ - "image/png", - "image/jpeg", - "application/json", - "text/html" - ] - } - ], - "signatures": [ - { - "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", - "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" - } - ] - }"""; -} \ No newline at end of file diff --git a/images/fork.jpg b/images/fork.jpg deleted file mode 100644 index b3888091f..000000000 Binary files a/images/fork.jpg and /dev/null differ diff --git a/integrations/microprofile-config/README.md b/integrations/microprofile-config/README.md deleted file mode 100644 index 501a0dd78..000000000 --- a/integrations/microprofile-config/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# A2A Java SDK - MicroProfile Config Integration - -This optional integration module provides MicroProfile Config support for the A2A Java SDK configuration system. - -## Overview - -The A2A Java SDK core uses the `A2AConfigProvider` interface for configuration, with default values loaded from `META-INF/a2a-defaults.properties` files on the classpath. - -This module provides `MicroProfileConfigProvider`, which integrates with MicroProfile Config to allow configuration via: -- `application.properties` -- Environment variables -- System properties (`-D` flags) -- Custom ConfigSources - -## Quick Start - -### 1. Add Dependency - -```xml - - io.github.a2asdk - a2a-java-sdk-microprofile-config - ${io.a2a.sdk.version} - -``` - -### 2. Configure Properties - -Once the dependency is added, you can override any A2A configuration property: - -**application.properties:** -```properties -# Executor configuration -a2a.executor.core-pool-size=10 -a2a.executor.max-pool-size=100 - -# Timeout configuration -a2a.blocking.agent.timeout.seconds=60 -a2a.blocking.consumption.timeout.seconds=10 -``` - -**Environment variables:** -```bash -export A2A_EXECUTOR_CORE_POOL_SIZE=10 -export A2A_BLOCKING_AGENT_TIMEOUT_SECONDS=60 -``` - -**System properties:** -```bash -java -Da2a.executor.core-pool-size=10 -jar your-app.jar -``` - -## How It Works - -The `MicroProfileConfigProvider` implementation: - -1. **First tries MicroProfile Config** - Checks `application.properties`, environment variables, system properties, and custom ConfigSources -2. **Falls back to defaults** - If not found, uses values from `META-INF/a2a-defaults.properties` provided by core modules and extras -3. **Priority 50** - Can be overridden by custom providers with higher priority - -## Configuration Fallback Chain - -``` -MicroProfile Config Sources (application.properties, env vars, -D flags) - ↓ (not found?) -DefaultValuesConfigProvider - → Scans classpath for ALL META-INF/a2a-defaults.properties files - → Merges all discovered properties together - → Throws exception if duplicate keys found - ↓ (property exists?) -Return merged default value - ↓ (not found?) -IllegalArgumentException -``` - -**Note**: All `META-INF/a2a-defaults.properties` files (from server-common, extras modules, etc.) are loaded and merged together by `DefaultValuesConfigProvider` at startup. This is not a sequential fallback chain, but a single merged set of defaults. - -## Available Configuration Properties - -See the [main README](../../README.md#configuration-system) for a complete list of configuration properties. - -## Framework Compatibility - -This module works with any MicroProfile Config implementation: - -- **Quarkus** - Built-in MicroProfile Config support -- **Helidon** - Built-in MicroProfile Config support -- **Open Liberty** - Built-in MicroProfile Config support -- **WildFly/JBoss EAP** - Add `smallrye-config` dependency -- **Other Jakarta EE servers** - Add MicroProfile Config implementation - -## Custom Config Providers - -If you're using a different framework (Spring, Micronaut, etc.), you can implement your own `A2AConfigProvider`: - -```java -import io.a2a.server.config.A2AConfigProvider; -import io.a2a.server.config.DefaultValuesConfigProvider; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Alternative; -import jakarta.annotation.Priority; -import jakarta.inject.Inject; - -@ApplicationScoped -@Alternative -@Priority(100) // Higher than MicroProfileConfigProvider's priority of 50 -public class OtherEnvironmentConfigProvider implements A2AConfigProvider { - - @Inject - Environment env; - - @Inject - DefaultValuesConfigProvider defaultValues; - - @Override - public String getValue(String name) { - String value = env.getProperty(name); - if (value != null) { - return value; - } - // Fallback to defaults - return defaultValues.getValue(name); - } - - @Override - public Optional getOptionalValue(String name) { - String value = env.getProperty(name); - if (value != null) { - return Optional.of(value); - } - return defaultValues.getOptionalValue(name); - } -} -``` - -## Implementation Details - -- **Package**: `io.a2a.integrations.microprofile` -- **Class**: `MicroProfileConfigProvider` -- **Priority**: 50 (can be overridden) -- **Scope**: `@ApplicationScoped` -- **Dependencies**: MicroProfile Config API, A2A SDK server-common - -## Reference Implementations - -The A2A Java SDK reference implementations (Quarkus-based) automatically include this integration module, so MicroProfile Config properties work out of the box. - -If you're building a custom server implementation, add this dependency to enable property-based configuration. diff --git a/integrations/microprofile-config/pom.xml b/integrations/microprofile-config/pom.xml deleted file mode 100644 index 1578f5c58..000000000 --- a/integrations/microprofile-config/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-microprofile-config - - jar - - A2A Java SDK - MicroProfile Config Integration - MicroProfile Config integration for A2A Java SDK - provides A2AConfigProvider implementation - - - - ${project.groupId} - a2a-java-sdk-server-common - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - org.eclipse.microprofile.config - microprofile-config-api - - - org.slf4j - slf4j-api - - - - - io.quarkus - quarkus-arc - test - - - io.quarkus - quarkus-junit5 - test - - - org.junit.jupiter - junit-jupiter-api - test - - - diff --git a/integrations/microprofile-config/src/main/java/io/a2a/integrations/microprofile/MicroProfileConfigProvider.java b/integrations/microprofile-config/src/main/java/io/a2a/integrations/microprofile/MicroProfileConfigProvider.java deleted file mode 100644 index 666c2d612..000000000 --- a/integrations/microprofile-config/src/main/java/io/a2a/integrations/microprofile/MicroProfileConfigProvider.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.a2a.integrations.microprofile; - -import java.util.Optional; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Alternative; -import jakarta.annotation.Priority; -import jakarta.inject.Inject; - -import io.a2a.server.config.A2AConfigProvider; -import io.a2a.server.config.DefaultValuesConfigProvider; -import org.eclipse.microprofile.config.Config; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * MicroProfile Config-based implementation of {@link A2AConfigProvider}. - *

- * This provider integrates with MicroProfile Config (used by Quarkus and other Jakarta EE runtimes) - * to allow configuration via standard sources: - *

    - *
  • System properties (-D flags)
  • - *
  • Environment variables
  • - *
  • application.properties
  • - *
  • Custom ConfigSources
  • - *
- *

- * Falls back to {@link DefaultValuesConfigProvider} when a configuration value is not found - * in MicroProfile Config, ensuring that default values from {@code META-INF/a2a-defaults.properties} - * are always available. - *

- * This provider is automatically enabled with {@code @Priority(50)}, but can be overridden by - * custom providers with higher priority. - *

- * To use this provider, add the {@code a2a-java-sdk-microprofile-config} dependency to your project. - */ -@ApplicationScoped -@Alternative -@Priority(50) -public class MicroProfileConfigProvider implements A2AConfigProvider { - - private static final Logger LOGGER = LoggerFactory.getLogger(MicroProfileConfigProvider.class); - - @Inject - Config mpConfig; - - @Inject - DefaultValuesConfigProvider defaultValues; - - @Override - public String getValue(String name) { - Optional value = mpConfig.getOptionalValue(name, String.class); - if (value.isPresent()) { - LOGGER.trace("Config value '{}' = '{}' (from MicroProfile Config)", name, value.get()); - return value.get(); - } - - // Fallback to defaults - String defaultValue = defaultValues.getValue(name); - LOGGER.trace("Config value '{}' = '{}' (from DefaultValuesConfigProvider)", name, defaultValue); - return defaultValue; - } - - @Override - public Optional getOptionalValue(String name) { - Optional value = mpConfig.getOptionalValue(name, String.class); - if (value.isPresent()) { - LOGGER.trace("Optional config value '{}' = '{}' (from MicroProfile Config)", name, value.get()); - return value; - } - - // Fallback to defaults - Optional defaultValue = defaultValues.getOptionalValue(name); - LOGGER.trace("Optional config value '{}' = '{}' (from DefaultValuesConfigProvider)", - name, defaultValue.orElse("")); - return defaultValue; - } -} diff --git a/integrations/microprofile-config/src/main/resources/META-INF/beans.xml b/integrations/microprofile-config/src/main/resources/META-INF/beans.xml deleted file mode 100644 index ffc8abb42..000000000 --- a/integrations/microprofile-config/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/integrations/microprofile-config/src/test/java/io/a2a/integrations/microprofile/MicroProfileConfigProviderTest.java b/integrations/microprofile-config/src/test/java/io/a2a/integrations/microprofile/MicroProfileConfigProviderTest.java deleted file mode 100644 index 6ad911145..000000000 --- a/integrations/microprofile-config/src/test/java/io/a2a/integrations/microprofile/MicroProfileConfigProviderTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package io.a2a.integrations.microprofile; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Optional; - -import jakarta.inject.Inject; - -import io.a2a.server.config.A2AConfigProvider; -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.Test; - -/** - * CDI-based test to verify that MicroProfileConfigProvider is properly selected - * and works correctly with MicroProfile Config and fallback to defaults. - */ -@QuarkusTest -public class MicroProfileConfigProviderTest { - - private static final String A2A_EXECUTOR_CORE_POOL_SIZE = "a2a.executor.core-pool-size"; - private static final String A2A_EXECUTOR_MAX_POOL_SIZE = "a2a.executor.max-pool-size"; - private static final String A2A_EXECUTOR_KEEP_ALIVE_SECONDS = "a2a.executor.keep-alive-seconds"; - - @Inject - A2AConfigProvider configProvider; - - @Test - public void testIsMicroProfileConfigProvider() { - // Verify that when microprofile-config module is on classpath, - // the injected A2AConfigProvider is the MicroProfile implementation - assertInstanceOf(MicroProfileConfigProvider.class, configProvider, - "A2AConfigProvider should be MicroProfileConfigProvider when module is present"); - } - - @Test - public void testGetValueFromMicroProfileConfig() { - // Test that values from application.properties override defaults - // The test application.properties sets a2a.executor.core-pool-size=15 - String value = configProvider.getValue(A2A_EXECUTOR_CORE_POOL_SIZE); - assertEquals("15", value, "Should get value from MicroProfile Config (application.properties)"); - } - - @Test - public void testGetValueFallbackToDefaults() { - // Test that values not in application.properties fall back to META-INF/a2a-defaults.properties - // a2a.executor.max-pool-size is not in test application.properties, so should use default - String value = configProvider.getValue(A2A_EXECUTOR_MAX_POOL_SIZE); - assertEquals("50", value, "Should fall back to default value from META-INF/a2a-defaults.properties"); - } - - @Test - public void testGetValueAnotherDefault() { - // Test another default property to ensure fallback works - String value = configProvider.getValue(A2A_EXECUTOR_KEEP_ALIVE_SECONDS); - assertEquals("60", value, "Should fall back to default value"); - } - - @Test - public void testGetOptionalValueFromMicroProfileConfig() { - // Test optional value that exists in application.properties - Optional value = configProvider.getOptionalValue(A2A_EXECUTOR_CORE_POOL_SIZE); - assertTrue(value.isPresent(), "Optional value should be present"); - assertEquals("15", value.get(), "Should get overridden value from MicroProfile Config"); - } - - @Test - public void testGetOptionalValueFallbackToDefaults() { - // Test optional value that falls back to defaults - Optional value = configProvider.getOptionalValue(A2A_EXECUTOR_MAX_POOL_SIZE); - assertTrue(value.isPresent(), "Optional value should be present from defaults"); - assertEquals("50", value.get(), "Should get default value"); - } - - @Test - public void testGetOptionalValueNotFound() { - // Test optional value that doesn't exist anywhere - Optional value = configProvider.getOptionalValue("non.existent.property"); - assertFalse(value.isPresent(), "Optional value should be empty for non-existent property"); - } - - @Test - public void testGetValueThrowsForNonExistent() { - // Test that required getValue() throws for non-existent property - assertThrows(IllegalArgumentException.class, - () -> configProvider.getValue("non.existent.property"), - "Should throw IllegalArgumentException for non-existent required property"); - } - - @Test - public void testSystemPropertyOverride() { - // System properties should have higher priority than application.properties - // Set a system property and verify it's used - String originalValue = System.getProperty("a2a.test.system.property"); - try { - System.setProperty("a2a.test.system.property", "from-system-property"); - String value = configProvider.getValue("a2a.test.system.property"); - assertEquals("from-system-property", value, - "System property should override application.properties"); - } finally { - if (originalValue != null) { - System.setProperty("a2a.test.system.property", originalValue); - } else { - System.clearProperty("a2a.test.system.property"); - } - } - } -} diff --git a/integrations/microprofile-config/src/test/resources/application.properties b/integrations/microprofile-config/src/test/resources/application.properties deleted file mode 100644 index a79c9b843..000000000 --- a/integrations/microprofile-config/src/test/resources/application.properties +++ /dev/null @@ -1,14 +0,0 @@ -# Test configuration for MicroProfileConfigProviderTest -# This overrides the default value to verify MicroProfile Config integration works - -# Override default value (default is 5) -a2a.executor.core-pool-size=15 - -# Note: a2a.executor.max-pool-size is NOT set here to test fallback to defaults -# Default value should be 50 from META-INF/a2a-defaults.properties - -# Exclude beans that aren't needed for config testing -quarkus.arc.exclude-types=io.a2a.server.requesthandlers.*,io.a2a.server.agentexecution.*,io.a2a.server.tasks.*,io.a2a.server.events.*,io.a2a.server.util.* - -# Property that will be overridden by a system property -a2a.test.system.property=from-application-properties \ No newline at end of file diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml deleted file mode 100644 index 4ffaaefde..000000000 --- a/jsonrpc-common/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - a2a-java-sdk-jsonrpc-common - - jar - - Java SDK A2A JSONRPC Common - Java SDK for the Agent2Agent Protocol (A2A) - Internal implementation utilities (not part of public API) - - - - ${project.groupId} - a2a-java-sdk-spec - - - com.google.code.gson - gson - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-params - test - - - - diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java deleted file mode 100644 index de56d119c..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -/** - * JSON mapping exception that includes request ID for error tracking. - */ -public class IdJsonMappingException extends JsonMappingException { - - /** - * The JSON-RPC request ID associated with this exception. - */ - private Object id; - - /** - * Constructs exception with message and ID. - * - * @param msg the error message - * @param id the request ID - */ - public IdJsonMappingException(String msg, Object id) { - super(msg); - this.id = id; - } - - /** - * Constructs exception with message, cause, and ID. - * - * @param msg the error message - * @param cause the cause - * @param id the request ID - */ - public IdJsonMappingException(String msg, Throwable cause, Object id) { - super(msg, cause); - this.id = id; - } - - /** - * Gets the request ID associated with this exception. - * - * @return the request ID - */ - public Object getId() { - return id; - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java deleted file mode 100644 index 5ac8c769c..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -/** - * Exception for invalid parameters during JSON mapping. - */ -public class InvalidParamsJsonMappingException extends IdJsonMappingException { - - /** - * Constructs exception with message and ID. - * - * @param msg the error message - * @param id the request ID - */ - public InvalidParamsJsonMappingException(String msg, Object id) { - super(msg, id); - } - - /** - * Constructs exception with message, cause, and ID. - * - * @param msg the error message - * @param cause the cause - * @param id the request ID - */ - public InvalidParamsJsonMappingException(String msg, Throwable cause, Object id) { - super(msg, cause, id); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java deleted file mode 100644 index dc85d6edb..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java +++ /dev/null @@ -1,102 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import org.jspecify.annotations.Nullable; - -/** - * Exception for JSON mapping errors when converting between JSON and Java objects. - *

- * This exception serves as a replacement for Jackson's JsonMappingException, allowing - * the A2A Java SDK to remain independent of any specific JSON library implementation. - * It represents errors that occur during the mapping phase of deserialization or - * serialization, such as type mismatches, invalid values, or constraint violations. - *

- * This exception extends {@link JsonProcessingException} and is used for more specific - * mapping-related errors compared to general parsing errors. - *

- * Usage example: - *

{@code
- * try {
- *     Task task = JsonUtil.fromJson(json, Task.class);
- *     if (task.id() == null) {
- *         throw new JsonMappingException(null, "Task ID cannot be null");
- *     }
- * } catch (JsonProcessingException e) {
- *     throw new JsonMappingException(null, "Invalid task format: " + e.getMessage(), e);
- * }
- * }
- * - * @see JsonProcessingException for the base exception class - */ -public class JsonMappingException extends JsonProcessingException { - - /** - * Optional reference object that caused the mapping error (e.g., JsonParser or field path). - */ - private final @Nullable Object reference; - - /** - * Constructs a new JsonMappingException with the specified reference and message. - *

- * The reference parameter can be used to provide context about where the mapping - * error occurred (e.g., a field name, path, or parser reference). It can be null - * if no specific reference is available. - * - * @param reference optional reference object providing context for the error (may be null) - * @param message the detail message explaining the mapping error - */ - public JsonMappingException(@Nullable Object reference, String message) { - super(message); - this.reference = reference; - } - - /** - * Constructs a new JsonMappingException with the specified reference, message, and cause. - *

- * The reference parameter can be used to provide context about where the mapping - * error occurred (e.g., a field name, path, or parser reference). It can be null - * if no specific reference is available. - * - * @param reference optional reference object providing context for the error (may be null) - * @param message the detail message explaining the mapping error - * @param cause the underlying cause of the mapping error (may be null) - */ - public JsonMappingException(@Nullable Object reference, String message, @Nullable Throwable cause) { - super(message, cause); - this.reference = reference; - } - - /** - * Constructs a new JsonMappingException with the specified message and cause. - *

- * This constructor is provided for compatibility when no reference object is needed. - * - * @param message the detail message explaining the mapping error - * @param cause the underlying cause of the mapping error (may be null) - */ - public JsonMappingException(String message, @Nullable Throwable cause) { - this(null, message, cause); - } - - /** - * Constructs a new JsonMappingException with the specified message. - *

- * This constructor is provided for compatibility when no reference object is needed. - * - * @param message the detail message explaining the mapping error - */ - public JsonMappingException(String message) { - this(null, message); - } - - /** - * Returns the reference object that provides context for the mapping error. - *

- * This may be null if no specific reference was available when the exception - * was created. - * - * @return the reference object, or null if not available - */ - public @Nullable Object getReference() { - return reference; - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java deleted file mode 100644 index cdbb7b4eb..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import org.jspecify.annotations.Nullable; - -/** - * General exception for JSON processing errors during serialization or deserialization. - *

- * This exception serves as a replacement for Jackson's JsonProcessingException, allowing - * the A2A Java SDK to remain independent of any specific JSON library implementation. - * It can be used with any JSON processing library (Gson, Jackson, etc.). - *

- * This is the base class for more specific JSON processing exceptions like - * {@link JsonMappingException}. - *

- * Usage example: - *

{@code
- * try {
- *     String json = gson.toJson(object);
- * } catch (Exception e) {
- *     throw new JsonProcessingException("Failed to serialize object", e);
- * }
- * }
- * - * @see JsonMappingException for mapping-specific errors - */ -public class JsonProcessingException extends Exception { - - /** - * Constructs a new JsonProcessingException with the specified message. - * - * @param message the detail message explaining the cause of the exception - */ - public JsonProcessingException(String message) { - super(message); - } - - /** - * Constructs a new JsonProcessingException with the specified message and cause. - * - * @param message the detail message explaining the cause of the exception - * @param cause the underlying cause of the exception (may be null) - */ - public JsonProcessingException(String message, @Nullable Throwable cause) { - super(message, cause); - } - - /** - * Constructs a new JsonProcessingException with the specified cause. - * - * @param cause the underlying cause of the exception - */ - public JsonProcessingException(Throwable cause) { - super(cause); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java deleted file mode 100644 index 4b473712d..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java +++ /dev/null @@ -1,971 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import static io.a2a.jsonrpc.common.json.JsonUtil.A2AErrorTypeAdapter.THROWABLE_MARKER_FIELD; -import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; -import static io.a2a.spec.DataPart.DATA; -import static io.a2a.spec.FilePart.FILE; -import static io.a2a.spec.TextPart.TEXT; -import static java.lang.String.format; -import static java.util.Collections.emptyMap; - -import java.io.StringReader; -import java.lang.reflect.Type; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonSyntaxException; -import com.google.gson.ToNumberPolicy; -import com.google.gson.TypeAdapter; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; - -import io.a2a.spec.A2AError; -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.DataPart; -import io.a2a.spec.FileContent; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.Message; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.MutualTLSSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.SecurityScheme; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; - -import org.jspecify.annotations.Nullable; - -/** - * Utility class for JSON operations. - */ -public class JsonUtil { - - private static GsonBuilder createBaseGsonBuilder() { - return new GsonBuilder() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) - .registerTypeAdapter(SecurityRequirement.class, new SecurityRequirementTypeAdapter()) - .registerTypeHierarchyAdapter(A2AError.class, new A2AErrorTypeAdapter()) - .registerTypeHierarchyAdapter(FileContent.class, new FileContentTypeAdapter()); - - } - - /** - * Pre-configured {@link Gson} instance for JSON operations. - *

- * This mapper is configured with strict parsing mode and all necessary custom TypeAdapters - * for A2A Protocol types including polymorphic types, enums, and date/time types. - *

- * Used throughout the SDK for consistent JSON serialization and deserialization. - * - * @see JsonUtil#createBaseGsonBuilder() - */ - public static final Gson OBJECT_MAPPER = createBaseGsonBuilder() - .registerTypeHierarchyAdapter(Part.class, new PartTypeAdapter()) - .registerTypeHierarchyAdapter(StreamingEventKind.class, new StreamingEventKindTypeAdapter()) - .registerTypeHierarchyAdapter(SecurityScheme.class, new SecuritySchemeTypeAdapter()) - .create(); - - /** - * Deserializes JSON string to an object of the specified class. - * - * @param the type of the object to deserialize to - * @param json the JSON string to parse - * @param classOfT the class of the object to deserialize to - * @return the deserialized object - * @throws JsonProcessingException if JSON parsing fails - */ - public static T fromJson(String json, Class classOfT) throws JsonProcessingException { - try { - return OBJECT_MAPPER.fromJson(json, classOfT); - } catch (JsonSyntaxException e) { - throw new JsonProcessingException("Failed to parse JSON", e); - } - } - - /** - * Deserializes JSON string to an object of the specified type. - * - * @param the type of the object to deserialize to - * @param json the JSON string to parse - * @param type the type of the object to deserialize to (supports generics) - * @return the deserialized object - * @throws JsonProcessingException if JSON parsing fails - */ - public static T fromJson(String json, Type type) throws JsonProcessingException { - try { - return OBJECT_MAPPER.fromJson(json, type); - } catch (JsonSyntaxException e) { - throw new JsonProcessingException("Failed to parse JSON", e); - } - } - - /** - * Serializes an object to a JSON string using Gson. - *

- * This method uses the pre-configured {@link #OBJECT_MAPPER} to produce - * JSON representation of the provided object. - * - * @param data the object to serialize - * @return JSON string representation of the object - * @throws JsonProcessingException if conversion fails - */ - public static String toJson(Object data) throws JsonProcessingException { - try { - return OBJECT_MAPPER.toJson(data); - } catch (JsonSyntaxException e) { - throw new JsonProcessingException("Failed to generate JSON", e); - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link OffsetDateTime} to/from ISO-8601 format. - *

- * This adapter ensures that OffsetDateTime instances are serialized to ISO-8601 formatted strings - * (e.g., "2023-10-01T12:00:00.234-05:00") and deserialized from the same format. - * This is necessary because Gson cannot access private fields of java.time classes via reflection - * in Java 17+ due to module system restrictions. - *

- * The adapter uses {@link DateTimeFormatter#ISO_OFFSET_DATE_TIME} for both serialization and - * deserialization, which ensures proper handling of timezone offsets. - * - * @see OffsetDateTime - * @see DateTimeFormatter#ISO_OFFSET_DATE_TIME - */ - static class OffsetDateTimeTypeAdapter extends TypeAdapter { - - @Override - public void write(JsonWriter out, OffsetDateTime value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - } else { - out.value(value.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); - } - } - - @Override - public @Nullable - OffsetDateTime read(JsonReader in) throws java.io.IOException { - if (in.peek() == com.google.gson.stream.JsonToken.NULL) { - in.nextNull(); - return null; - } - String dateTimeString = in.nextString(); - try { - return OffsetDateTime.parse(dateTimeString, DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } catch (DateTimeParseException e) { - throw new JsonSyntaxException("Failed to parse OffsetDateTime: " + dateTimeString, e); - } - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link Throwable} and its subclasses. - *

- * This adapter avoids reflection into {@link Throwable}'s private fields, which is not allowed - * in Java 17+ due to module system restrictions. Instead, it serializes Throwables as simple - * objects containing only the type (fully qualified class name) and message. - *

- * Serialization: Converts a Throwable to a JSON object with: - *

    - *
  • "type": The fully qualified class name (e.g., "java.lang.IllegalArgumentException")
  • - *
  • "message": The exception message
  • - *
- *

- * Deserialization: Reads the JSON and reconstructs the Throwable using reflection to find - * a constructor that accepts a String message parameter. If no such constructor exists or if - * instantiation fails, returns a generic {@link RuntimeException} with the message. - * - * @see Throwable - */ - static class ThrowableTypeAdapter extends TypeAdapter { - - @Override - public void write(JsonWriter out, Throwable value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - out.beginObject(); - out.name("type").value(value.getClass().getName()); - out.name("message").value(value.getMessage()); - out.name(THROWABLE_MARKER_FIELD).value(true); - out.endObject(); - } - - @Override - public @Nullable - Throwable read(JsonReader in) throws java.io.IOException { - if (in.peek() == com.google.gson.stream.JsonToken.NULL) { - in.nextNull(); - return null; - } - - String type = null; - String message = null; - - in.beginObject(); - while (in.hasNext()) { - String fieldName = in.nextName(); - switch (fieldName) { - case "type" -> - type = in.nextString(); - case "message" -> - message = in.nextString(); - default -> - in.skipValue(); - } - } - in.endObject(); - - // Try to reconstruct the Throwable - if (type != null) { - try { - Class throwableClass = Class.forName(type); - if (Throwable.class.isAssignableFrom(throwableClass)) { - // Try to find a constructor that takes a String message - try { - var constructor = throwableClass.getConstructor(String.class); - return (Throwable) constructor.newInstance(message); - } catch (NoSuchMethodException e) { - // No String constructor, return a generic RuntimeException - return new RuntimeException(message); - } - } - } catch (Exception e) { - // If we can't reconstruct the exact type, return a generic RuntimeException - return new RuntimeException(message); - } - } - return new RuntimeException(message); - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link A2AError} and its subclasses. - *

- * This adapter handles polymorphic deserialization based on the error code, creating the - * appropriate subclass instance. - *

- * The adapter maps error codes to their corresponding error classes: - *

    - *
  • -32700: {@link JSONParseError}
  • - *
  • -32600: {@link InvalidRequestError}
  • - *
  • -32601: {@link MethodNotFoundError}
  • - *
  • -32602: {@link InvalidParamsError}
  • - *
  • -32603: {@link InternalError}
  • - *
  • -32001: {@link TaskNotFoundError}
  • - *
  • -32002: {@link TaskNotCancelableError}
  • - *
  • -32003: {@link PushNotificationNotSupportedError}
  • - *
  • -32004: {@link UnsupportedOperationError}
  • - *
  • -32005: {@link ContentTypeNotSupportedError}
  • - *
  • -32006: {@link InvalidAgentResponseError}
  • - *
  • Other codes: {@link A2AError}
  • - *
- * - * @see A2AError - */ - static class A2AErrorTypeAdapter extends TypeAdapter { - - private static final ThrowableTypeAdapter THROWABLE_ADAPTER = new ThrowableTypeAdapter(); - static final String THROWABLE_MARKER_FIELD = "__throwable"; - private static final String CODE_FIELD = "code"; - private static final String DATA_FIELD = "data"; - private static final String MESSAGE_FIELD = "message"; - private static final String TYPE_FIELD = "type"; - - @Override - public void write(JsonWriter out, A2AError value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - out.beginObject(); - out.name(CODE_FIELD).value(value.getCode()); - out.name(MESSAGE_FIELD).value(value.getMessage()); - if (value.getData() != null) { - out.name(DATA_FIELD); - // If data is a Throwable, use ThrowableTypeAdapter to avoid reflection issues - if (value.getData() instanceof Throwable throwable) { - THROWABLE_ADAPTER.write(out, throwable); - } else { - // Use Gson to serialize the data field for non-Throwable types - OBJECT_MAPPER.toJson(value.getData(), Object.class, out); - } - } - out.endObject(); - } - - @Override - public @Nullable - A2AError read(JsonReader in) throws java.io.IOException { - if (in.peek() == com.google.gson.stream.JsonToken.NULL) { - in.nextNull(); - return null; - } - - Integer code = null; - String message = null; - Object data = null; - - in.beginObject(); - while (in.hasNext()) { - String fieldName = in.nextName(); - switch (fieldName) { - case CODE_FIELD -> - code = in.nextInt(); - case MESSAGE_FIELD -> - message = in.nextString(); - case DATA_FIELD -> { - // Read data as a generic object (could be string, number, object, etc.) - data = readDataValue(in); - } - default -> - in.skipValue(); - } - } - in.endObject(); - - // Create the appropriate subclass based on the error code - return createErrorInstance(code, message, data); - } - - /** - * Reads the data field value, which can be of any JSON type. - */ - private @Nullable - Object readDataValue(JsonReader in) throws java.io.IOException { - return switch (in.peek()) { - case STRING -> - in.nextString(); - case NUMBER -> - in.nextDouble(); - case BOOLEAN -> - in.nextBoolean(); - case NULL -> { - in.nextNull(); - yield null; - } - case BEGIN_OBJECT -> { - // Parse as JsonElement to check if it's a Throwable - com.google.gson.JsonElement element = com.google.gson.JsonParser.parseReader(in); - if (element.isJsonObject()) { - com.google.gson.JsonObject obj = element.getAsJsonObject(); - // Check if it has the structure of a serialized Throwable (type + message) - if (obj.has(TYPE_FIELD) && obj.has(MESSAGE_FIELD) && obj.has(THROWABLE_MARKER_FIELD)) { - // Deserialize as Throwable using ThrowableTypeAdapter - yield THROWABLE_ADAPTER.read(new JsonReader(new StringReader(element.toString()))); - } - } - // Otherwise, deserialize as generic object - yield OBJECT_MAPPER.fromJson(element, Object.class); - } - case BEGIN_ARRAY -> - // For arrays, read as raw JSON using Gson - OBJECT_MAPPER.fromJson(in, Object.class); - default -> { - in.skipValue(); - yield null; - } - }; - } - - /** - * Creates the appropriate A2AError subclass based on the error code. - */ - private A2AError createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - if (code == null) { - throw new JsonSyntaxException("A2AError must have a code field"); - } - - return switch (code) { - case JSON_PARSE_ERROR_CODE -> - new JSONParseError(code, message, data); - case INVALID_REQUEST_ERROR_CODE -> - new InvalidRequestError(code, message, data); - case METHOD_NOT_FOUND_ERROR_CODE -> - new MethodNotFoundError(code, message, data); - case INVALID_PARAMS_ERROR_CODE -> - new InvalidParamsError(code, message, data); - case INTERNAL_ERROR_CODE -> - new io.a2a.spec.InternalError(code, message, data); - case TASK_NOT_FOUND_ERROR_CODE -> - new TaskNotFoundError(code, message, data); - case TASK_NOT_CANCELABLE_ERROR_CODE -> - new TaskNotCancelableError(code, message, data); - case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE -> - new PushNotificationNotSupportedError(code, message, data); - case UNSUPPORTED_OPERATION_ERROR_CODE -> - new UnsupportedOperationError(code, message, data); - case CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE -> - new ContentTypeNotSupportedError(code, message, data); - case INVALID_AGENT_RESPONSE_ERROR_CODE -> - new InvalidAgentResponseError(code, message, data); - default -> - new A2AError(code, message == null ? "" : message, data); - }; - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link Part} and its subclasses. - *

- * This adapter handles polymorphic deserialization, creating the - * appropriate subclass instance (TextPart, FilePart, or DataPart) based on available fields. - *

- * The adapter uses a two-pass approach: first reads the JSON as a tree to inspect the "kind" - * field, then deserializes to the appropriate concrete type. - * - * @see Part - * @see TextPart - * @see FilePart - * @see DataPart - */ - static class PartTypeAdapter extends TypeAdapter> { - - private static final Set VALID_KEYS = Set.of(TEXT, FILE, DATA); - private static final Type MAP_TYPE = new TypeToken>(){}.getType(); - - // Create separate Gson instance without the Part adapter to avoid recursion - private final Gson delegateGson = createBaseGsonBuilder().create(); - - private void writeMetadata(JsonWriter out, @Nullable Map metadata) throws java.io.IOException { - if (metadata != null && !metadata.isEmpty()) { - out.name("metadata"); - delegateGson.toJson(metadata, MAP_TYPE, out); - } - } - - @Override - public void write(JsonWriter out, Part value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - // Write wrapper object with member name as discriminator - out.beginObject(); - - if (value instanceof TextPart textPart) { - // TextPart: { "text": "value" } - direct string value - out.name(TEXT); - out.value(textPart.text()); - writeMetadata(out, textPart.metadata()); - } else if (value instanceof FilePart filePart) { - // FilePart: { "file": {...} } - out.name(FILE); - delegateGson.toJson(filePart.file(), FileContent.class, out); - writeMetadata(out, filePart.metadata()); - } else if (value instanceof DataPart dataPart) { - // DataPart: { "data": } - out.name(DATA); - delegateGson.toJson(dataPart.data(), Object.class, out); - writeMetadata(out, dataPart.metadata()); - } else { - throw new JsonSyntaxException("Unknown Part subclass: " + value.getClass().getName()); - } - - out.endObject(); - } - - @Override - public @Nullable - Part read(JsonReader in) throws java.io.IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - - // Read the JSON as a tree to inspect the member name discriminator - com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); - if (!jsonElement.isJsonObject()) { - throw new JsonSyntaxException("Part must be a JSON object"); - } - - com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); - - // Extract metadata if present - Map metadata = null; - if (jsonObject.has("metadata")) { - metadata = delegateGson.fromJson(jsonObject.get("metadata"), new TypeToken>(){}.getType()); - } - - // Check for member name discriminators (v1.0 protocol) - Set keys = jsonObject.keySet(); - if (keys.size() < 1 || keys.size() > 2) { - throw new JsonSyntaxException(format("Part object must have one content key from %s and optionally 'metadata' (found: %s)", VALID_KEYS, keys)); - } - - // Find the discriminator (should be one of TEXT, FILE, DATA) - String discriminator = keys.stream() - .filter(VALID_KEYS::contains) - .findFirst() - .orElseThrow(() -> new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, keys))); - - return switch (discriminator) { - case TEXT -> new TextPart(jsonObject.get(TEXT).getAsString(), metadata); - case FILE -> new FilePart(delegateGson.fromJson(jsonObject.get(FILE), FileContent.class), metadata); - case DATA -> { - // DataPart supports any JSON value: object, array, primitive, or null - Object data = delegateGson.fromJson( - jsonObject.get(DATA), - Object.class - ); - yield new DataPart(data, metadata); - } - default -> - throw new JsonSyntaxException(format("Part must have one of: %s (found: %s)", VALID_KEYS, discriminator)); - }; - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link StreamingEventKind} and its implementations. - *

- * This adapter handles polymorphic deserialization based on the "kind" field, creating the - * appropriate implementation instance (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent). - *

- * The adapter uses a two-pass approach: first reads the JSON as a tree to inspect the "kind" - * field, then deserializes to the appropriate concrete type. - * - * @see StreamingEventKind - * @see Task - * @see Message - * @see TaskStatusUpdateEvent - * @see TaskArtifactUpdateEvent - */ - static class StreamingEventKindTypeAdapter extends TypeAdapter { - - // Create separate Gson instance without the StreamingEventKind adapter to avoid recursion - private final Gson delegateGson = createBaseGsonBuilder() - .registerTypeHierarchyAdapter(Part.class, new PartTypeAdapter()) - .create(); - - @Override - public void write(JsonWriter out, StreamingEventKind value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - // Write wrapper object with member name as discriminator - out.beginObject(); - out.name(value.kind()); - delegateGson.toJson(value, value.getClass(), out); - out.endObject(); - } - - @Override - public @Nullable - StreamingEventKind read(JsonReader in) throws java.io.IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - - // Read the JSON as a tree to inspect the member name discriminator - com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); - if (!jsonElement.isJsonObject()) { - throw new JsonSyntaxException("StreamingEventKind must be a JSON object"); - } - - com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); - - // Check for wrapped member name discriminators (v1.0 protocol - streaming format) - if (jsonObject.has(Task.STREAMING_EVENT_ID)) { - return delegateGson.fromJson(jsonObject.get(Task.STREAMING_EVENT_ID), Task.class); - } else if (jsonObject.has(Message.STREAMING_EVENT_ID)) { - return delegateGson.fromJson(jsonObject.get(Message.STREAMING_EVENT_ID), Message.class); - } else if (jsonObject.has(TaskStatusUpdateEvent.STREAMING_EVENT_ID)) { - return delegateGson.fromJson( - jsonObject.get(TaskStatusUpdateEvent.STREAMING_EVENT_ID), TaskStatusUpdateEvent.class); - } else if (jsonObject.has(TaskArtifactUpdateEvent.STREAMING_EVENT_ID)) { - return delegateGson.fromJson( - jsonObject.get(TaskArtifactUpdateEvent.STREAMING_EVENT_ID), TaskArtifactUpdateEvent.class); - } - - // Check for unwrapped format (direct Task/Message deserialization) - // Task objects have "id" and "contextId" fields - // Message objects have "role" and "messageId" fields - if (jsonObject.has("role") && jsonObject.has("messageId")) { - // This is an unwrapped Message - return delegateGson.fromJson(jsonObject, Message.class); - } else if (jsonObject.has("id") && jsonObject.has("contextId")) { - // This is an unwrapped Task - return delegateGson.fromJson(jsonObject, Task.class); - } else if (jsonObject.has("taskId") && jsonObject.has("status")) { - // This is an unwrapped TaskStatusUpdateEvent - return delegateGson.fromJson(jsonObject, TaskStatusUpdateEvent.class); - } else if (jsonObject.has("taskId") && jsonObject.has("artifact")) { - // This is an unwrapped TaskArtifactUpdateEvent - return delegateGson.fromJson(jsonObject, TaskArtifactUpdateEvent.class); - } else { - throw new JsonSyntaxException("StreamingEventKind must have wrapper (task/message/statusUpdate/artifactUpdate) or recognizable unwrapped fields (found: " + jsonObject.keySet() + ")"); - } - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link FileContent} and its implementations. - *

- * This adapter handles polymorphic deserialization for the sealed FileContent interface, - * which permits two implementations: - *

    - *
  • {@link FileWithBytes} - File content embedded as base64-encoded bytes
  • - *
  • {@link FileWithUri} - File content referenced by URI
  • - *
- *

- * The adapter distinguishes between the two types by checking for the presence of - * "bytes" or "uri" fields in the JSON object. - * - * @see FileContent - * @see FileWithBytes - * @see FileWithUri - */ - static class FileContentTypeAdapter extends TypeAdapter { - - // Create separate Gson instance without the FileContent adapter to avoid recursion - private final Gson delegateGson = new GsonBuilder() - .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) - .create(); - - @Override - public void write(JsonWriter out, FileContent value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - // Delegate to Gson's default serialization for the concrete type - delegateGson.toJson(value, value.getClass(), out); - } - - @Override - public @Nullable - FileContent read(JsonReader in) throws java.io.IOException { - if (in.peek() == com.google.gson.stream.JsonToken.NULL) { - in.nextNull(); - return null; - } - - // Read the JSON as a tree to inspect the fields - com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); - if (!jsonElement.isJsonObject()) { - throw new JsonSyntaxException("FileContent must be a JSON object"); - } - - com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); - - // Distinguish between FileWithBytes and FileWithUri by checking for "bytes" or "uri" field - if (jsonObject.has("bytes")) { - return delegateGson.fromJson(jsonElement, FileWithBytes.class); - } else if (jsonObject.has("uri")) { - return delegateGson.fromJson(jsonElement, FileWithUri.class); - } else { - throw new JsonSyntaxException("FileContent must have either 'bytes' or 'uri' field"); - } - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link APIKeySecurityScheme.Location} enum. - *

- * This adapter ensures that Location enum values are serialized using their - * wire format string representation (e.g., "header") rather than - * the Java enum constant name (e.g., "HEADER"). - *

- * For serialization, it uses {@link APIKeySecurityScheme.Location#asString()} to get the wire format. - * For deserialization, it uses {@link APIKeySecurityScheme.Location#fromString(String)} to parse the - * wire format back to the enum constant. - * - * @see APIKeySecurityScheme.Location - */ - static class APIKeyLocationTypeAdapter extends TypeAdapter { - - @Override - public void write(JsonWriter out, APIKeySecurityScheme.Location value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - out.value(value.asString()); - } - - @Override - public APIKeySecurityScheme.@Nullable Location read(JsonReader in) throws java.io.IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - String locationString = in.nextString(); - try { - return APIKeySecurityScheme.Location.fromString(locationString); - } catch (IllegalArgumentException e) { - throw new JsonSyntaxException("Invalid APIKeySecurityScheme.Location: " + locationString, e); - } - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link SecurityScheme} and its implementations. - *

- * This adapter handles polymorphic deserialization for the sealed SecurityScheme interface, - * which permits five implementations: - *

    - *
  • {@link APIKeySecurityScheme} - API key authentication
  • - *
  • {@link HTTPAuthSecurityScheme} - HTTP authentication (basic or bearer)
  • - *
  • {@link OAuth2SecurityScheme} - OAuth 2.0 flows
  • - *
  • {@link OpenIdConnectSecurityScheme} - OpenID Connect discovery
  • - *
  • {@link MutualTLSSecurityScheme} - Client certificate authentication
  • - *
- *

- * The adapter uses a wrapper object with the security scheme type as the discriminator field. - * Each SecurityScheme is serialized as a JSON object with a single field whose name identifies - * the security scheme type. - *

- * Serialization format examples: - *

{@code
-     * // HTTPAuthSecurityScheme
-     * {
-     *   "httpAuthSecurityScheme": {
-     *     "scheme": "bearer",
-     *     "bearerFormat": "JWT",
-     *     "description": "..."
-     *   }
-     * }
-     *
-     * // APIKeySecurityScheme
-     * {
-     *   "apiKeySecurityScheme": {
-     *     "location": "header",
-     *     "name": "X-API-Key",
-     *     "description": "..."
-     *   }
-     * }
-     * }
- * - * @see SecurityScheme - * @see APIKeySecurityScheme - * @see HTTPAuthSecurityScheme - * @see OAuth2SecurityScheme - * @see OpenIdConnectSecurityScheme - * @see MutualTLSSecurityScheme - */ - static class SecuritySchemeTypeAdapter extends TypeAdapter { - - private static final Set VALID_KEYS = Set.of(APIKeySecurityScheme.TYPE, - HTTPAuthSecurityScheme.TYPE, - OAuth2SecurityScheme.TYPE, - OpenIdConnectSecurityScheme.TYPE, - MutualTLSSecurityScheme.TYPE); - - // Create separate Gson instance without the SecurityScheme adapter to avoid recursion - // Register custom adapter for APIKeySecurityScheme.Location enum - private final Gson delegateGson = createBaseGsonBuilder() - .registerTypeAdapter(APIKeySecurityScheme.Location.class, new APIKeyLocationTypeAdapter()) - .create(); - - @Override - public void write(JsonWriter out, SecurityScheme value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - - // Write wrapper object with member name as discriminator - out.beginObject(); - out.name(value.type()); - delegateGson.toJson(value, value.getClass(), out); - out.endObject(); - } - - @Override - public @Nullable - SecurityScheme read(JsonReader in) throws java.io.IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - - // Read the JSON as a tree to inspect the member name discriminator - com.google.gson.JsonElement jsonElement = com.google.gson.JsonParser.parseReader(in); - if (!jsonElement.isJsonObject()) { - throw new JsonSyntaxException("SecurityScheme must be a JSON object"); - } - - com.google.gson.JsonObject jsonObject = jsonElement.getAsJsonObject(); - - // Check for member name discriminators - Set keys = jsonObject.keySet(); - if (keys.size() != 1) { - throw new JsonSyntaxException(format("A SecurityScheme object must have exactly one key, which must be one of: %s (found: %s)", VALID_KEYS, keys)); - } - - String discriminator = keys.iterator().next(); - com.google.gson.JsonElement nestedObject = jsonObject.get(discriminator); - - return switch (discriminator) { - case APIKeySecurityScheme.TYPE -> delegateGson.fromJson(nestedObject, APIKeySecurityScheme.class); - case HTTPAuthSecurityScheme.TYPE -> delegateGson.fromJson(nestedObject, HTTPAuthSecurityScheme.class); - case OAuth2SecurityScheme.TYPE -> delegateGson.fromJson(nestedObject, OAuth2SecurityScheme.class); - case OpenIdConnectSecurityScheme.TYPE -> delegateGson.fromJson(nestedObject, OpenIdConnectSecurityScheme.class); - case MutualTLSSecurityScheme.TYPE -> delegateGson.fromJson(nestedObject, MutualTLSSecurityScheme.class); - default -> throw new JsonSyntaxException(format("Unknown SecurityScheme type. Must be one of: %s (found: %s)", VALID_KEYS, discriminator)); - }; - } - } - - /** - * Gson TypeAdapter for serializing and deserializing {@link SecurityRequirement}. - *

- * This adapter handles the JSON structure where a SecurityRequirement is represented - * as an object with a "schemes" field containing a map of security scheme names to - * StringList objects (matching the protobuf representation). - *

- * Serialization format: - *

{@code
-     * {
-     *   "schemes": {
-     *     "oauth2": { "list": ["read", "write"] },
-     *     "apiKey": { "list": [] }
-     *   }
-     * }
-     * }
- * - * @see SecurityRequirement - */ - static class SecurityRequirementTypeAdapter extends TypeAdapter { - - private static final String SCHEMES_FIELD = "schemes"; - private static final String LIST_FIELD = "list"; - - @Override - public void write(JsonWriter out, SecurityRequirement value) throws java.io.IOException { - if (value == null) { - out.nullValue(); - return; - } - - out.beginObject(); - out.name(SCHEMES_FIELD); - - Map> schemes = value.schemes(); - if (schemes == null || schemes.isEmpty()) { - out.beginObject(); - out.endObject(); - } else { - out.beginObject(); - for (Map.Entry> entry : schemes.entrySet()) { - out.name(entry.getKey()); - out.beginObject(); - out.name(LIST_FIELD); - out.beginArray(); - List scopes = entry.getValue(); - if (scopes != null) { - for (String scope : scopes) { - out.value(scope); - } - } - out.endArray(); - out.endObject(); - } - out.endObject(); - } - - out.endObject(); - } - - @Override - public @Nullable SecurityRequirement read(JsonReader in) throws java.io.IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - - Map> schemes = emptyMap(); - - in.beginObject(); - while (in.hasNext()) { - String fieldName = in.nextName(); - if (SCHEMES_FIELD.equals(fieldName)) { - schemes = readSchemesMap(in); - } else { - in.skipValue(); - } - } - in.endObject(); - - return new SecurityRequirement(schemes); - } - - private Map> readSchemesMap(JsonReader in) throws java.io.IOException { - Map> schemes = new LinkedHashMap<>(); - - in.beginObject(); - while (in.hasNext()) { - String schemeName = in.nextName(); - List scopes = readStringList(in); - schemes.put(schemeName, scopes); - } - in.endObject(); - - return schemes; - } - - private List readStringList(JsonReader in) throws java.io.IOException { - List scopes = new ArrayList<>(); - - in.beginObject(); - while (in.hasNext()) { - String fieldName = in.nextName(); - if (LIST_FIELD.equals(fieldName)) { - in.beginArray(); - while (in.hasNext()) { - scopes.add(in.nextString()); - } - in.endArray(); - } else { - in.skipValue(); - } - } - in.endObject(); - - return scopes; - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java deleted file mode 100644 index 5bac1c026..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import io.a2a.spec.MethodNotFoundError; - -/** - * Exception thrown when JSON mapping fails due to a method not found error. - *

- * This exception is used during JSON-RPC request deserialization when the requested - * method cannot be found or mapped. It extends {@link IdJsonMappingException} to - * preserve the request ID for error responses. - * - * @see IdJsonMappingException - * @see MethodNotFoundError - */ -public class MethodNotFoundJsonMappingException extends IdJsonMappingException { - - /** - * Constructs exception with message and request ID. - * - * @param msg the error message - * @param id the JSON-RPC request ID - */ - public MethodNotFoundJsonMappingException(String msg, Object id) { - super(msg, id); - } - - /** - * Constructs exception with message, cause, and request ID. - * - * @param msg the error message - * @param cause the underlying cause - * @param id the JSON-RPC request ID - */ - public MethodNotFoundJsonMappingException(String msg, Throwable cause, Object id) { - super(msg, cause, id); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java deleted file mode 100644 index e6f547b92..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * JSON processing exceptions for the A2A Java SDK. - *

- * This package provides custom exceptions that replace Jackson's JSON processing exceptions, - * allowing the SDK to be independent of any specific JSON library implementation. - */ -@org.jspecify.annotations.NullMarked -package io.a2a.jsonrpc.common.json; diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java deleted file mode 100644 index e2f91c35a..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.util.Assert; - -/** - * Represents a JSON-RPC 2.0 error response. - *

- * An error response is returned when a request cannot be processed successfully. - * According to the JSON-RPC 2.0 specification, an error response must contain: - *

    - *
  • {@code jsonrpc} - Always "2.0"
  • - *
  • {@code error} - A {@link A2AError} object describing the error
  • - *
  • {@code id} - The request ID, or null if the ID could not be determined
  • - *
- *

- * The {@code result} field must be absent or null in error responses. This class - * enforces that constraint by fixing the result type parameter to {@code Void}. - * - * @see A2AError - * @see A2AResponse - * @see JSON-RPC 2.0 Response Object - */ -public final class A2AErrorResponse extends A2AResponse { - - /** - * Constructs a JSON-RPC error response with all fields. - *

- * This constructor is used for JSON deserialization. - * - * @param jsonrpc the JSON-RPC version (must be "2.0") - * @param id the request ID, or null if the ID could not be determined from the request - * @param result must be null for error responses - * @param error the error object describing what went wrong (required) - * @throws IllegalArgumentException if error is null - */ - public A2AErrorResponse(String jsonrpc, Object id, Void result, A2AError error) { - super(jsonrpc, id, result, error, Void.class); - Assert.checkNotNullParam("error", error); - } - - /** - * Constructs a JSON-RPC error response with a request ID and error. - *

- * The jsonrpc field defaults to "2.0". - * - * @param id the request ID - * @param error the error object (required) - */ - public A2AErrorResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - /** - * Constructs a JSON-RPC error response without a request ID. - *

- * Use this constructor when the request ID could not be determined, - * typically for parse errors or malformed requests. - * - * @param error the error object (required) - */ - public A2AErrorResponse(A2AError error) { - this(null, null, null, error); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java deleted file mode 100644 index 183b8359f..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -/** - * Base interface for all JSON-RPC 2.0 protocol messages in the A2A Protocol. - *

- * This sealed interface defines the fundamental structure shared by all JSON-RPC 2.0 - * messages used in the A2A Protocol's JSON-RPC transport layer. It ensures type safety - * and exhaustiveness checking by permitting only {@link A2ARequest} and {@link A2AResponse} - * as implementing types. - *

- * According to the JSON-RPC 2.0 specification, all messages must include a {@code jsonrpc} - * version field set to "2.0", and may optionally include an {@code id} field for correlation - * between requests and responses. - * - * @see A2ARequest - * @see A2AResponse - * @see JSON-RPC 2.0 Specification - * @see A2A Protocol Specification - */ -public sealed interface A2AMessage permits A2ARequest, A2AResponse { - - /** - * The JSON-RPC protocol version string as defined by the JSON-RPC 2.0 specification. - * All messages must have their {@code jsonrpc} field set to this value. - */ - String JSONRPC_VERSION = "2.0"; - - /** - * Gets the JSON-RPC version for this message. - *

- * According to the JSON-RPC 2.0 specification, this must be exactly "2.0". - * - * @return the JSON-RPC version string, always {@value #JSONRPC_VERSION} - */ - String getJsonrpc(); - - /** - * Gets the request/response correlation identifier. - *

- * The ID is used to match responses with their corresponding requests. It may be - * a String, Integer, or null for notification-style requests that do not expect a response. - * - * @return the correlation ID, or null for notifications - */ - Object getId(); - -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java deleted file mode 100644 index e7200219a..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java +++ /dev/null @@ -1,109 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.util.Assert; -import io.a2a.util.Utils; - -/** - * Base class for JSON-RPC 2.0 requests in the A2A Protocol. - *

- * This sealed class represents a JSON-RPC 2.0 request message with parameterized support - * for different request parameter types. It enforces the JSON-RPC 2.0 specification - * requirements while providing type safety through generic parameters. - *

- * A JSON-RPC request consists of: - *

    - *
  • {@code jsonrpc} - The protocol version (always "2.0")
  • - *
  • {@code method} - The name of the method to invoke
  • - *
  • {@code params} - Method parameters (optional, type varies by method)
  • - *
  • {@code id} - Correlation identifier for matching with responses (optional for notifications)
  • - *
- *

- * This class is sealed to ensure only {@link NonStreamingJSONRPCRequest} and - * {@link StreamingJSONRPCRequest} can extend it, providing compile-time guarantees - * about request types. - * - * @param the type of the params object for this request - * @see NonStreamingJSONRPCRequest - * @see StreamingJSONRPCRequest - * @see JSON-RPC 2.0 Specification - * @see A2A Protocol Specification - */ -public abstract sealed class A2ARequest implements A2AMessage permits NonStreamingJSONRPCRequest, StreamingJSONRPCRequest { - - /** The JSON-RPC protocol version. */ - protected String jsonrpc; - - /** The request identifier. */ - protected Object id; - - /** The method name to invoke. */ - protected String method; - - /** The method parameters. */ - protected T params; - - /** - * Default constructor for JSON deserialization. - */ - public A2ARequest() { - } - - /** - * {@inheritDoc} - */ - @Override - public String getJsonrpc() { - return this.jsonrpc; - } - - /** - * {@inheritDoc} - */ - @Override - public Object getId() { - return this.id; - } - - /** - * Gets the name of the method to be invoked. - * - * @return the method name - */ - public String getMethod() { - return this.method; - } - - /** - * Gets the parameters to be passed to the method. - * - * @return the method parameters, or null if none - */ - public T getParams() { - return this.params; - } - - /** - * Validates and sets JSON-RPC parameters. - * - * @param jsonrpc the JSON-RPC version - * @param method the method name - * @param id the request ID - * @param params the parameters - * @param paramsIsRequired whether parameters are required - */ - protected void validateAndSetJsonParameters(String jsonrpc, String method, Object id, T params, boolean paramsIsRequired) { - this.jsonrpc = Utils.defaultIfNull(jsonrpc, JSONRPC_VERSION); - if (!JSONRPC_VERSION.equals(this.jsonrpc)) { - throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); - } - Assert.checkNotNullParam("method", method); - this.method = method; - Assert.isNullOrStringOrInteger(id); - this.id = id; - if (paramsIsRequired) { - Assert.checkNotNullParam("params", params); - } - this.params = params; - } - -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java deleted file mode 100644 index 20fc4bd42..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java +++ /dev/null @@ -1,83 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.util.Utils.defaultIfNull; - -import io.a2a.spec.A2AError; -import io.a2a.util.Assert; - -/** - * Represents a JSONRPC response. - * - * @param the type of the result value returned in successful responses - */ -public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetExtendedAgentCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, CreateTaskPushNotificationConfigResponse { - - /** The JSON-RPC protocol version. */ - protected String jsonrpc; - /** The request identifier this response corresponds to. */ - protected Object id; - /** The result of the method invocation. */ - protected T result; - /** The error object if the invocation failed. */ - protected A2AError error; - - /** - * Default constructor for deserialization. - */ - public A2AResponse() { - } - - /** - * Constructs a JSON-RPC response. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the result value - * @param error the error if any - * @param resultType the result type class - */ - public A2AResponse(String jsonrpc, Object id, T result, A2AError error, Class resultType) { - if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { - throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); - } - if (error != null && result != null) { - throw new IllegalArgumentException("Invalid JSON-RPC error response"); - } - if (error == null && result == null && ! Void.class.equals(resultType)) { - throw new IllegalArgumentException("Invalid JSON-RPC success response"); - } - Assert.isNullOrStringOrInteger(id); - this.jsonrpc = defaultIfNull(jsonrpc, JSONRPC_VERSION); - this.id = id; - this.result = result; - this.error = error; - } - - @Override - public String getJsonrpc() { - return this.jsonrpc; - } - - @Override - public Object getId() { - return this.id; - } - - /** - * Gets the result value. - * - * @return the result - */ - public T getResult() { - return this.result; - } - - /** - * Gets the error object. - * - * @return the error if any - */ - public A2AError getError() { - return this.error; - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java deleted file mode 100644 index 463279705..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java +++ /dev/null @@ -1,129 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; - -import java.util.UUID; - -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskState; - -/** - * JSON-RPC request to cancel an in-progress task. - *

- * This request instructs the agent to cancel execution of a specific task identified by ID. - * The agent should stop processing, clean up resources, and transition the task to - * {@link TaskState#TASK_STATE_CANCELED} state if cancellation is possible. - *

- * Not all tasks can be canceled (e.g., already completed tasks), which may result in - * a {@link TaskNotCancelableError}. - *

- * This class implements the JSON-RPC {@code tasks/cancel} method as specified in the A2A Protocol. - * - * @see CancelTaskResponse for the corresponding response - * @see TaskIdParams for the parameter structure - * @see TaskNotCancelableError for the error when cancellation is not possible - * @see A2A Protocol Specification - */ -public final class CancelTaskRequest extends NonStreamingJSONRPCRequest { - - /** - * Creates a new CancelTaskRequest with the specified JSON-RPC parameters. - * - * @param jsonrpc the JSON-RPC version (defaults to "2.0" if null) - * @param id the request identifier (string, integer, or null) - * @param params the request parameters containing the task ID - * @throws IllegalArgumentException if jsonrpc version is invalid, method is not "CancelTask", params is null, or id is not a String/Integer/null - */ - public CancelTaskRequest(String jsonrpc, Object id, TaskIdParams params) { - super(jsonrpc, CANCEL_TASK_METHOD, id, params); - } - - /** - * Creates a new CancelTaskRequest with default JSON-RPC version and method. - * - * @param id the request identifier (string, integer, or null) - * @param params the request parameters containing the task ID - * @throws IllegalArgumentException if params is null or id is not a string/integer/null - */ - public CancelTaskRequest(Object id, TaskIdParams params) { - this(null, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link CancelTaskRequest} instances. - *

- * Provides a fluent API for setting request parameters. If no id is provided, - * a random UUID will be generated when {@link #build()} is called. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private TaskIdParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC protocol version. - * - * @param jsonrpc the JSON-RPC version (optional, defaults to "2.0") - * @return this builder for method chaining - */ - - public CancelTaskRequest.Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request identifier. - * - * @param id the request identifier (string, integer, or null; if null, a UUID will be generated) - * @return this builder for method chaining - */ - public CancelTaskRequest.Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the request parameters containing the task ID to cancel. - * - * @param params the request parameters (required) - * @return this builder for method chaining - */ - - public CancelTaskRequest.Builder params(TaskIdParams params) { - this.params = params; - return this; - } - - /** - * Builds a new {@link CancelTaskRequest} from the current builder state. - *

- * If no id was provided, a random UUID will be generated. - * - * @return a new CancelTaskRequest instance - * @throws IllegalArgumentException if validation fails (invalid method, null params, invalid id type) - */ - public CancelTaskRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new CancelTaskRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java deleted file mode 100644 index 8a7ca6413..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskResponse.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskState; - -/** - * JSON-RPC response for task cancellation requests. - *

- * This response contains the updated {@link Task} object after cancellation, typically - * showing {@link TaskState#TASK_STATE_CANCELED} status if the cancellation was successful. - *

- * If the task cannot be canceled (e.g., already completed) or is not found, the error - * field will contain a {@link io.a2a.spec.A2AError} such as {@link TaskNotCancelableError} or - * {@link TaskNotFoundError}. - * - * @see CancelTaskRequest for the corresponding request - * @see Task for the task structure - * @see TaskNotCancelableError for the error when cancellation fails - * @see A2A Protocol Specification - */ - -public final class CancelTaskResponse extends A2AResponse { - - /** - * Constructs a CancelTaskResponse with full parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the task result - * @param error the error if any - */ - public CancelTaskResponse(String jsonrpc, Object id, Task result, A2AError error) { - super(jsonrpc, id, result, error, Task.class); - } - - /** - * Constructs a CancelTaskResponse with an error. - * - * @param id the request ID - * @param error the error - */ - public CancelTaskResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - - /** - * Constructs a CancelTaskResponse with a successful result. - * - * @param id the request ID - * @param result the task result - */ - public CancelTaskResponse(Object id, Task result) { - this(null, id, result, null); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java deleted file mode 100644 index b9b8716be..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,115 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; - -import java.util.UUID; - -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.TaskPushNotificationConfig; - -/** - * JSON-RPC request to configure push notifications for a specific task. - *

- * This request registers or updates the push notification endpoint for a task, enabling - * the agent to send asynchronous updates (status changes, artifact additions) to the - * specified URL without requiring client polling. - *

- * This class implements the JSON-RPC {@code tasks/pushNotificationConfig/set} method. - * - * @see CreateTaskPushNotificationConfigResponse for the response - * @see TaskPushNotificationConfig for the parameter structure - * @see PushNotificationConfig for notification endpoint details - * @see A2A Protocol Specification - */ -public final class CreateTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - - /** - * Constructs request with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param params the request parameters - */ - public CreateTaskPushNotificationConfigRequest(String jsonrpc, Object id, TaskPushNotificationConfig params) { - super(jsonrpc, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); - } - - /** - * Constructs request with ID and parameters. - * - * @param id the request ID - * @param taskPushConfig the task push notification configuration - */ - public CreateTaskPushNotificationConfigRequest(String id, TaskPushNotificationConfig taskPushConfig) { - this(null, id, taskPushConfig); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private TaskPushNotificationConfig params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC version. - * - * @param jsonrpc the JSON-RPC version - * @return this builder for method chaining - */ - public CreateTaskPushNotificationConfigRequest.Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request ID. - * - * @param id the request ID - * @return this builder for method chaining - */ - public CreateTaskPushNotificationConfigRequest.Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the request parameters. - * - * @param params the request parameters - * @return this builder for method chaining - */ - public CreateTaskPushNotificationConfigRequest.Builder params(TaskPushNotificationConfig params) { - this.params = params; - return this; - } - - /** - * Builds the instance. - * - * @return a new instance - */ - public CreateTaskPushNotificationConfigRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new CreateTaskPushNotificationConfigRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java deleted file mode 100644 index e46aa7d2b..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CreateTaskPushNotificationConfigResponse.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.TaskPushNotificationConfig; - -/** - * JSON-RPC response confirming push notification configuration for a task. - *

- * This response confirms that the push notification configuration has been successfully - * registered for the task. The result contains the full {@link TaskPushNotificationConfig} - * as stored by the agent. - *

- * If push notifications are not supported or an error occurs, the error field will contain - * a {@link A2AError} (e.g., {@link PushNotificationNotSupportedError}). - * - * @see CreateTaskPushNotificationConfigRequest for the corresponding request - * @see TaskPushNotificationConfig for the configuration structure - * @see PushNotificationNotSupportedError for the error when unsupported - * @see A2A Protocol Specification - */ -public final class CreateTaskPushNotificationConfigResponse extends A2AResponse { - - /** - * Constructs response with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the push notification configuration - * @param error the error (if any) - */ - public CreateTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPushNotificationConfig result, A2AError error) { - super(jsonrpc, id, result, error, TaskPushNotificationConfig.class); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public CreateTaskPushNotificationConfigResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - /** - * Constructs success response. - * - * @param id the request ID - * @param result the push notification configuration - */ - public CreateTaskPushNotificationConfigResponse(Object id, TaskPushNotificationConfig result) { - this(null, id, result, null); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java deleted file mode 100644 index 64f983520..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,122 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - - -import java.util.UUID; - -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; - -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; - -/** - * JSON-RPC request to delete a push notification configuration from a task. - *

- * This request removes a specific push notification endpoint configuration from a task, - * stopping future notifications to that endpoint. The task will continue execution, but - * no longer send updates to the deleted notification URL. - *

- * This class implements the JSON-RPC {@code tasks/pushNotificationConfig/delete} method. - * - * @see DeleteTaskPushNotificationConfigResponse for the response - * @see DeleteTaskPushNotificationConfigParams for the parameter structure - * @see A2A Protocol Specification - */ -public final class DeleteTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - - /** - * Creates a new DeleteTaskPushNotificationConfigRequest with the specified JSON-RPC parameters. - * - * @param jsonrpc the JSON-RPC version (defaults to "2.0" if null) - * @param id the request identifier (string, integer, or null) - * @param params the request parameters containing task and config IDs - * @throws IllegalArgumentException if jsonrpc version is invalid, method is not "DeleteTaskPushNotificationConfig", or id is not a string/integer/null - */ - public DeleteTaskPushNotificationConfigRequest(String jsonrpc, Object id, DeleteTaskPushNotificationConfigParams params) { - super(jsonrpc, DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); - } - - /** - * Creates a new DeleteTaskPushNotificationConfigRequest with default JSON-RPC version and method. - * - * @param id the request identifier (string, integer, or null) - * @param params the request parameters containing task and config IDs - * @throws IllegalArgumentException if id is not a string/integer/null - */ - public DeleteTaskPushNotificationConfigRequest(String id, DeleteTaskPushNotificationConfigParams params) { - this(null, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link DeleteTaskPushNotificationConfigRequest} instances. - *

- * Provides a fluent API for setting request parameters. If no id is provided, - * a random UUID will be generated when {@link #build()} is called. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private DeleteTaskPushNotificationConfigParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC protocol version. - * - * @param jsonrpc the JSON-RPC version (optional, defaults to "2.0") - * @return this builder for method chaining - */ - public Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request identifier. - * - * @param id the request identifier (string, integer, or null; if null, a UUID will be generated) - * @return this builder for method chaining - */ - public Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the request parameters. - * - * @param params the request parameters containing task and config IDs (required) - * @return this builder for method chaining - */ - public Builder params(DeleteTaskPushNotificationConfigParams params) { - this.params = params; - return this; - } - - /** - * Builds a new {@link DeleteTaskPushNotificationConfigRequest} from the current builder state. - *

- * If no id was provided, a random UUID will be generated. - * - * @return a new DeleteTaskPushNotificationConfigRequest instance - * @throws IllegalArgumentException if validation fails (invalid method, invalid id type) - */ - public DeleteTaskPushNotificationConfigRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new DeleteTaskPushNotificationConfigRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java deleted file mode 100644 index d25674814..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; - -/** - * JSON-RPC response confirming deletion of a task's push notification configuration. - *

- * This response confirms successful deletion of the push notification configuration. - * The result is void (no content) on success. - *

- * If an error occurs during deletion, the error field will contain a {@link A2AError}. - * - * @see DeleteTaskPushNotificationConfigRequest for the corresponding request - * @see A2A Protocol Specification - */ -public final class DeleteTaskPushNotificationConfigResponse extends A2AResponse { - - /** - * Creates a new DeleteTaskPushNotificationConfigResponse with full JSON-RPC parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the response identifier matching the request - * @param result the result (always null/Void for this response type) - * @param error the error if the request failed, null on success - */ - public DeleteTaskPushNotificationConfigResponse(String jsonrpc, Object id, Void result,A2AError error) { - super(jsonrpc, id, result, error, Void.class); - } - - /** - * Creates a new error DeleteTaskPushNotificationConfigResponse with default JSON-RPC version. - * - * @param id the response identifier matching the request - * @param error the error describing why the deletion failed - */ - public DeleteTaskPushNotificationConfigResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - /** - * Creates a new successful DeleteTaskPushNotificationConfigResponse with default JSON-RPC version. - * - * @param id the response identifier matching the request - */ - public DeleteTaskPushNotificationConfigResponse(Object id) { - this(null, id, null, null); - } - -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java deleted file mode 100644 index 89e893363..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardRequest.java +++ /dev/null @@ -1,112 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; - -import java.util.UUID; - -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; - -/** - * JSON-RPC request to retrieve an agent's extended card with authenticated details. - *

- * This request fetches an extended version of the {@link AgentCard} that may contain - * additional information only available to authenticated clients, such as: - *

    - *
  • Additional security scheme details
  • - *
  • Extended capability information
  • - *
  • Authenticated-only skills or interfaces
  • - *
  • Premium or restricted features
  • - *
- *

- * The agent must support authenticated extended cards (indicated by - * {@link AgentCapabilities#extendedAgentCard()} }) and the client must provide - * valid authentication credentials for this request to succeed. - *

- * This class implements the JSON-RPC {@code GetExtendedAgentCard} method - * as specified in the A2A Protocol. - * - * @see GetExtendedAgentCardResponse for the corresponding response - * @see AgentCard for the card structure - * @see ExtendedAgentCardNotConfiguredError for the error when unsupported - * @see A2A Protocol Specification - */ -public final class GetExtendedAgentCardRequest extends NonStreamingJSONRPCRequest { - - /** - * Constructs request with full parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - */ - public GetExtendedAgentCardRequest(String jsonrpc, Object id) { - super(jsonrpc, GET_EXTENDED_AGENT_CARD_METHOD, id); - } - - /** - * Constructs request with ID only (uses default JSON-RPC version). - * - * @param id the request ID - */ - public GetExtendedAgentCardRequest(String id) { - this(null, id); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private String jsonrpc; - private Object id; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC version. - * - * @param jsonrpc the JSON-RPC version - * @return this builder for method chaining - */ - public GetExtendedAgentCardRequest.Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request ID. - * - * @param id the request ID - * @return this builder for method chaining - */ - public GetExtendedAgentCardRequest.Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Builds the instance. - * - * @return a new instance - */ - public GetExtendedAgentCardRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new GetExtendedAgentCardRequest(jsonrpc, id); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java deleted file mode 100644 index edf181dd6..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetExtendedAgentCardResponse.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; - -/** - * JSON-RPC response containing an agent's extended card with authenticated details. - *

- * This response returns an {@link AgentCard} with additional information only available - * to authenticated clients. The extended card may include premium features, detailed - * security configurations, or other authenticated-only capabilities. - *

- * If the agent doesn't support authenticated extended cards or authentication fails, - * the error field will contain a {@link A2AError} such as - * {@link ExtendedAgentCardNotConfiguredError}. - * - * @see GetExtendedAgentCardRequest for the corresponding request - * @see AgentCard for the card structure - * @see ExtendedAgentCardNotConfiguredError for the error when unsupported - * @see A2A Protocol Specification - */ -public final class GetExtendedAgentCardResponse extends A2AResponse { - - /** - * Constructs response with full parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the agent card result - * @param error the error if any - */ - public GetExtendedAgentCardResponse(String jsonrpc, Object id, AgentCard result, A2AError error) { - super(jsonrpc, id, result, error, AgentCard.class); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public GetExtendedAgentCardResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - /** - * Constructs successful response. - * - * @param id the request ID - * @param result the agent card result - */ - public GetExtendedAgentCardResponse(Object id, AgentCard result) { - this(null, id, result, null); - } - -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java deleted file mode 100644 index e0f11be83..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,114 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; - -import java.util.UUID; - -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.TaskPushNotificationConfig; - -/** - * JSON-RPC request to retrieve push notification configuration for a task. - *

- * This request retrieves the currently configured push notification endpoint and settings - * for a specific task, allowing clients to verify or inspect the notification configuration. - *

- * This class implements the JSON-RPC {@code tasks/pushNotificationConfig/get} method. - * - * @see GetTaskPushNotificationConfigResponse for the response - * @see GetTaskPushNotificationConfigParams for the parameter structure - * @see TaskPushNotificationConfig for the returned configuration - * @see A2A Protocol Specification - */ -public final class GetTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - - /** - * Constructs request with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param params the request parameters - */ - public GetTaskPushNotificationConfigRequest(String jsonrpc, Object id, GetTaskPushNotificationConfigParams params) { - super(jsonrpc, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); - } - - /** - * Constructs request with ID and parameters. - * - * @param id the request ID - * @param params the request parameters - */ - public GetTaskPushNotificationConfigRequest(String id, GetTaskPushNotificationConfigParams params) { - this(null, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private GetTaskPushNotificationConfigParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the jsonrpc. - * - * @param jsonrpc the jsonrpc - * @return this builder for method chaining - */ - public GetTaskPushNotificationConfigRequest.Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request ID. - * - * @param id the request ID - * @return this builder for method chaining - */ - public GetTaskPushNotificationConfigRequest.Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the request parameters. - * - * @param params the request parameters - * @return this builder for method chaining - */ - public GetTaskPushNotificationConfigRequest.Builder params(GetTaskPushNotificationConfigParams params) { - this.params = params; - return this; - } - - /** - * Builds the instance. - * - * @return a new instance - */ - public GetTaskPushNotificationConfigRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new GetTaskPushNotificationConfigRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java deleted file mode 100644 index 3aa71c8b6..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java +++ /dev/null @@ -1,53 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.TaskPushNotificationConfig; - -/** - * JSON-RPC response containing a task's push notification configuration. - *

- * This response returns the {@link TaskPushNotificationConfig} for the requested task, - * showing the current push notification endpoint and authentication settings. - *

- * If no configuration exists or an error occurs, the error field will contain a - * {@link A2AError}. - * - * @see GetTaskPushNotificationConfigRequest for the corresponding request - * @see TaskPushNotificationConfig for the configuration structure - * @see A2A Protocol Specification - */ -public final class GetTaskPushNotificationConfigResponse extends A2AResponse { - - /** - * Constructs response with full parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the push notification config result - * @param error the error if any - */ - public GetTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPushNotificationConfig result, A2AError error) { - super(jsonrpc, id, result, error, TaskPushNotificationConfig.class); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public GetTaskPushNotificationConfigResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - /** - * Constructs successful response. - * - * @param id the request ID - * @param result the push notification config result - */ - public GetTaskPushNotificationConfigResponse(Object id, TaskPushNotificationConfig result) { - this(null, id, result, null); - } - -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java deleted file mode 100644 index a08abe1be..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java +++ /dev/null @@ -1,115 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; - -import java.util.UUID; - -import io.a2a.spec.Task; -import io.a2a.spec.TaskQueryParams; - -/** - * JSON-RPC request to retrieve task information by ID. - *

- * This request queries the agent for the current state of a specific task, including its - * status, artifacts, messages, and other task metadata. Clients use this to check task - * progress or retrieve completed task results. - *

- * This class implements the JSON-RPC {@code tasks/get} method as specified in the A2A Protocol. - * - * @see GetTaskResponse for the corresponding response - * @see TaskQueryParams for the parameter structure - * @see Task for the returned task structure - * @see A2A Protocol Specification - */ -public final class GetTaskRequest extends NonStreamingJSONRPCRequest { - - /** - * Constructs request with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param params the request parameters - */ - public GetTaskRequest(String jsonrpc, Object id, TaskQueryParams params) { - super(jsonrpc, GET_TASK_METHOD, id, params); - } - - /** - * Constructs request with ID and parameters. - * - * @param id the request ID - * @param params the request parameters - */ - public GetTaskRequest(Object id, TaskQueryParams params) { - this(null, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private TaskQueryParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC version. - * - * @param jsonrpc the JSON-RPC version - * @return this builder for method chaining - */ - public GetTaskRequest.Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request ID. - * - * @param id the request ID - * @return this builder for method chaining - */ - public GetTaskRequest.Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the request parameters. - * - * @param params the request parameters - * @return this builder for method chaining - */ - public GetTaskRequest.Builder params(TaskQueryParams params) { - this.params = params; - return this; - } - - /** - * Builds the instance. - * - * @return a new instance - */ - public GetTaskRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new GetTaskRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskResponse.java deleted file mode 100644 index 68ea1ed90..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskResponse.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotFoundError; - -/** - * JSON-RPC response containing requested task information. - *

- * This response returns the full {@link Task} object for a task ID queried via - * {@link GetTaskRequest}, including all task metadata, status, artifacts, and messages. - *

- * If the task is not found or an error occurs, the error field will be populated with - * a {@link A2AError} (typically {@link TaskNotFoundError}) instead of a result. - * - * @see GetTaskRequest for the corresponding request - * @see Task for the task structure - * @see TaskNotFoundError for the common error case - * @see A2A Protocol Specification - */ -public final class GetTaskResponse extends A2AResponse { - - /** - * Constructs response with full parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the task result - * @param error the error if any - */ - public GetTaskResponse(String jsonrpc, Object id, Task result, A2AError error) { - super(jsonrpc, id, result, error, Task.class); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public GetTaskResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - /** - * Constructs successful response. - * - * @param id the request ID - * @param result the task result - */ - public GetTaskResponse(Object id, Task result) { - this(null, id, result, null); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigRequest.java deleted file mode 100644 index ebd5c98e5..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,115 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - - -import java.util.UUID; - -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.TaskPushNotificationConfig; - -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; - -/** - * JSON-RPC request to list all push notification configurations for a task. - *

- * This request retrieves all configured push notification endpoints for a specific task, - * allowing clients to enumerate all active notification subscriptions. - *

- * This class implements the JSON-RPC {@code tasks/pushNotificationConfig/list} method. - * - * @see ListTaskPushNotificationConfigResponse for the response - * @see ListTaskPushNotificationConfigParams for the parameter structure - * @see TaskPushNotificationConfig for the configuration structure - * @see A2A Protocol Specification - */ -public final class ListTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - - /** - * Constructs request with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param params the request parameters - */ - public ListTaskPushNotificationConfigRequest(String jsonrpc, Object id, ListTaskPushNotificationConfigParams params) { - super(jsonrpc, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); - } - - /** - * Constructs request with ID and parameters. - * - * @param id the request ID - * @param params the request parameters - */ - public ListTaskPushNotificationConfigRequest(String id, ListTaskPushNotificationConfigParams params) { - this(null, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private ListTaskPushNotificationConfigParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the jsonrpc. - * - * @param jsonrpc the jsonrpc - * @return this builder for method chaining - */ - public Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the id. - * - * @param id the id - * @return this builder for method chaining - */ - public Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the params. - * - * @param params the params - * @return this builder for method chaining - */ - public Builder params(ListTaskPushNotificationConfigParams params) { - this.params = params; - return this; - } - - /** - * Builds the instance. - * - * @return a new instance - */ - public ListTaskPushNotificationConfigRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new ListTaskPushNotificationConfigRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java deleted file mode 100644 index e5e24739f..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.TaskPushNotificationConfig; - -/** - * JSON-RPC response containing all push notification configurations for a task with pagination support. - *

- * This response returns a {@link ListTaskPushNotificationConfigResult} containing - * {@link TaskPushNotificationConfig} entries configured for the requested task, - * showing all active notification endpoints with optional pagination information. - *

- * If an error occurs, the error field will contain a {@link A2AError}. - * - * @see ListTaskPushNotificationConfigRequest for the corresponding request - * @see ListTaskPushNotificationConfigResult for the result structure - * @see TaskPushNotificationConfig for the configuration structure - * @see A2A Protocol Specification - */ -public final class ListTaskPushNotificationConfigResponse extends A2AResponse { - - /** - * Constructs response with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the result containing list of push notification configurations and pagination info - * @param error the error (if any) - */ - public ListTaskPushNotificationConfigResponse(String jsonrpc, Object id, ListTaskPushNotificationConfigResult result, A2AError error) { - super(jsonrpc, id, result, error, ListTaskPushNotificationConfigResult.class); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public ListTaskPushNotificationConfigResponse(Object id, A2AError error) { - this(null, id, null, error); - } - - /** - * Constructs success response. - * - * @param id the request ID - * @param result the result containing list of push notification configurations and pagination info - */ - public ListTaskPushNotificationConfigResponse(Object id, ListTaskPushNotificationConfigResult result) { - this(null, id, result, null); - } - -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java deleted file mode 100644 index aa8d656bc..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java +++ /dev/null @@ -1,103 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; - -import java.util.UUID; - -import io.a2a.spec.ListTasksParams; - -/** - * A list tasks request. - */ -public final class ListTasksRequest extends NonStreamingJSONRPCRequest { - - /** - * Constructs request with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param params the request parameters - */ - public ListTasksRequest(String jsonrpc, Object id, ListTasksParams params) { - super(jsonrpc, LIST_TASK_METHOD, id, params); - } - - /** - * Constructs request with ID and parameters. - * - * @param id the request ID - * @param params the request parameters - */ - public ListTasksRequest(Object id, ListTasksParams params) { - this(JSONRPC_VERSION, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private ListTasksParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the jsonrpc. - * - * @param jsonrpc the jsonrpc - * @return this builder for method chaining - */ - public Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the id. - * - * @param id the id - * @return this builder for method chaining - */ - public Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the params. - * - * @param params the params - * @return this builder for method chaining - */ - public Builder params(ListTasksParams params) { - this.params = params; - return this; - } - - /** - * Builds the instance. - * - * @return a new instance - */ - public ListTasksRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new ListTasksRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResponse.java deleted file mode 100644 index 8fa6446cb..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResponse.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; - -/** - * The response for a list tasks request. - */ -public final class ListTasksResponse extends A2AResponse { - - /** - * Constructs response with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the result - * @param error the error if any - */ - public ListTasksResponse(String jsonrpc, Object id, ListTasksResult result, A2AError error) { - super(jsonrpc, id, result, error, ListTasksResult.class); - } - - /** - * Constructs successful response. - * - * @param id the request ID - * @param result the result - */ - public ListTasksResponse(Object id, ListTasksResult result) { - this(null, id, result, null); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public ListTasksResponse(Object id, A2AError error) { - this(null, id, null, error); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java deleted file mode 100644 index 9cf2adc60..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java +++ /dev/null @@ -1,144 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import java.util.List; - -import io.a2a.spec.Task; -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Result of a list tasks request containing matching tasks and pagination information. - * - * @param tasks Array of tasks matching the specified criteria - * @param totalSize Total number of tasks available (before pagination) - * @param pageSize Number of tasks returned in this response - * @param nextPageToken Token for retrieving the next page of results (null if no more results) - */ -public record ListTasksResult( - List tasks, - int totalSize, - int pageSize, - @Nullable String nextPageToken -) { - /** - * Compact constructor for validation. - * Validates parameters and creates a defensive copy of the tasks list. - * - * @param tasks the list of tasks - * @param totalSize total number of tasks available - * @param pageSize number of tasks in this page - * @param nextPageToken token for next page - * @throws IllegalArgumentException if validation fails - */ - public ListTasksResult { - Assert.checkNotNullParam("tasks", tasks); - if (totalSize < 0) { - throw new IllegalArgumentException("totalSize must be non-negative"); - } - if (pageSize < 0) { - throw new IllegalArgumentException("pageSize must be non-negative"); - } - if (pageSize != tasks.size()) { - throw new IllegalArgumentException("pageSize must be equal to the number of tasks in the list. Got " + pageSize + ", but list has " + tasks.size() + " tasks."); - } - // Make defensive copy - tasks = List.copyOf(tasks); - } - - /** - * Constructor for results without pagination. - * - * @param tasks the list of tasks - */ - public ListTasksResult(List tasks) { - this(tasks, tasks.size(), tasks.size(), null); - } - - /** - * Returns whether there are more results available. - * - * @return true if there are more pages of results - */ - public boolean hasMoreResults() { - return nextPageToken != null && !nextPageToken.isEmpty(); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private List tasks; - private int totalSize; - private int pageSize; - private String nextPageToken; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the tasks list. - * - * @param tasks the list of tasks - * @return this builder for method chaining - */ - public Builder tasks(List tasks) { - this.tasks = tasks; - return this; - } - - /** - * Sets the totalSize. - * - * @param totalSize the totalSize - * @return this builder for method chaining - */ - public Builder totalSize(int totalSize) { - this.totalSize = totalSize; - return this; - } - - /** - * Sets the pageSize. - * - * @param pageSize the pageSize - * @return this builder for method chaining - */ - public Builder pageSize(int pageSize) { - this.pageSize = pageSize; - return this; - } - - /** - * Sets the nextPageToken. - * - * @param nextPageToken the nextPageToken - * @return this builder for method chaining - */ - public Builder nextPageToken(String nextPageToken) { - this.nextPageToken = nextPageToken; - return this; - } - - /** - * Builds the ListTasksResult. - * - * @return a new ListTasksResult instance - * @throws IllegalArgumentException if validation fails - */ - public ListTasksResult build() { - return new ListTasksResult(tasks, totalSize, pageSize, nextPageToken); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java deleted file mode 100644 index 80d64b199..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -/** - * Represents a non-streaming JSON-RPC request. - * - * @param the type of the request parameters - */ -public abstract sealed class NonStreamingJSONRPCRequest extends A2ARequest permits GetTaskRequest, - CancelTaskRequest, CreateTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, - SendMessageRequest, DeleteTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigRequest, - GetExtendedAgentCardRequest, ListTasksRequest { - - NonStreamingJSONRPCRequest(String jsonrpc, String method, Object id, T params) { - validateAndSetJsonParameters(jsonrpc, method, id, params, true); - } - - NonStreamingJSONRPCRequest(String jsonrpc, String method, Object id) { - validateAndSetJsonParameters(jsonrpc, method, id, null, false); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java deleted file mode 100644 index 999361635..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java +++ /dev/null @@ -1,141 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; - -import java.util.UUID; - -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Task; - -/** - * JSON-RPC request for the {@code SendMessage} method in the A2A Protocol. - *

- * This request initiates a new task or continues an existing task by sending a message - * to an agent. The request returns a single response containing the final {@link Task} - * state once processing completes (blocking/non-streaming mode). - *

- * The {@code SendMessage} method is used for: - *

    - *
  • Creating new tasks with an initial user message
  • - *
  • Continuing existing tasks with additional messages
  • - *
  • Restarting tasks with new context
  • - *
- *

- * For real-time event streaming during task execution, use {@link SendStreamingMessageRequest} - * with the {@code SendStreamingMessage} method instead. - *

- * This class includes a fluent {@link Builder} for convenient request construction. The method - * name is fixed as "SendMessage" and is set automatically by the constructor. - * - * @see SendStreamingMessageRequest - * @see MessageSendParams - * @see Task - * @see A2A Protocol Specification - */ -public final class SendMessageRequest extends NonStreamingJSONRPCRequest { - - /** - * Constructs a SendMessageRequest with the specified JSON-RPC fields. - *

- * This constructor is used for JSON deserialization and validates - * that the method name is exactly "SendMessage". - * - * @param jsonrpc the JSON-RPC version (must be "2.0") - * @param id the request correlation identifier (String, Integer, or null) - * @param params the message send parameters (required) - * @throws IllegalArgumentException if validation fails - */ - public SendMessageRequest(String jsonrpc, Object id, MessageSendParams params) { - super(jsonrpc, SEND_MESSAGE_METHOD, id, params); - } - - /** - * Constructs a SendMessageRequest with default JSON-RPC version. - * - * @param id the request correlation identifier - * @param params the message send parameters (required) - */ - public SendMessageRequest(Object id, MessageSendParams params) { - this(JSONRPC_VERSION, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link SendMessageRequest} instances with a fluent API. - *

- * The method name is automatically set to "SendMessage" and cannot be changed. - * If no ID is provided, a UUID will be auto-generated when {@link #build()} is called. - *

- * Example usage: - *

{@code
-     * SendMessageRequest request = SendMessageRequest.builder()
-     *     .params(new MessageSendParams(message, taskId, pushNotificationConfig))
-     *     .build();
-     * }
- */ - public static class Builder { - private String jsonrpc; - private Object id; - private MessageSendParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC version. - * - * @param jsonrpc the JSON-RPC version (typically "2.0") - * @return this builder for method chaining - */ - public Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request correlation ID. - * - * @param id the request correlation identifier - * @return this builder for method chaining - */ - public Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the message send parameters (required). - * - * @param params the message send parameters - * @return this builder for method chaining - */ - public Builder params(MessageSendParams params) { - this.params = params; - return this; - } - - /** - * Builds the SendMessageRequest. - * Auto-generates a UUID for the ID if not set. - * - * @return the constructed request - */ - public SendMessageRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new SendMessageRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java deleted file mode 100644 index 4f576dd01..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.EventKind; - -/** - * The response after receiving a send message request. - */ -public final class SendMessageResponse extends A2AResponse { - - /** - * Constructs response with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the result - * @param error the error if any - */ - public SendMessageResponse(String jsonrpc, Object id, EventKind result, A2AError error) { - super(jsonrpc, id, result, error, EventKind.class); - } - - /** - * Constructs successful response. - * - * @param id the request ID - * @param result the result - */ - public SendMessageResponse(Object id, EventKind result) { - this(null, id, result, null); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public SendMessageResponse(Object id, A2AError error) { - this(null, id, null, error); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java deleted file mode 100644 index 704b70435..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java +++ /dev/null @@ -1,121 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; - -import java.util.UUID; - -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; - -/** - * JSON-RPC request to initiate a new task with streaming event delivery. - *

- * This request starts agent processing for a message and immediately returns a stream of events - * representing the agent's progress and responses. Unlike {@link SendMessageRequest}, this enables - * real-time progress updates as the agent processes the request. - *

- * The streaming response provides {@link StreamingEventKind} events such as task updates, - * artifact additions, and status changes as they occur, rather than waiting for final completion. - *

- * This class implements the JSON-RPC {@code message/stream} method as specified in the A2A Protocol. - * - * @see SendMessageRequest for non-streaming message delivery - * @see MessageSendParams for parameter structure - * @see StreamingEventKind for event types in streaming responses - * @see A2A Protocol Specification - */ -public final class SendStreamingMessageRequest extends StreamingJSONRPCRequest { - - /** - * Constructs request with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param params the request parameters - */ - public SendStreamingMessageRequest(String jsonrpc, Object id, MessageSendParams params) { - super(jsonrpc, SEND_STREAMING_MESSAGE_METHOD, id, params); - } - - /** - * Constructs request with ID and parameters. - * - * @param id the request ID - * @param params the request parameters - */ - public SendStreamingMessageRequest(Object id, MessageSendParams params) { - this(null, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link SendStreamingMessageRequest} instances. - *

- * Provides a fluent API for building streaming message requests with optional customization - * of JSON-RPC protocol fields. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private MessageSendParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC protocol version. - * - * @param jsonrpc the JSON-RPC version (defaults to "2.0") - * @return this builder - */ - public Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the JSON-RPC request ID. - * - * @param id the request identifier (auto-generated UUID if null) - * @return this builder - */ - public Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the message send parameters. - * - * @param params the parameters containing the message and configuration - * @return this builder - */ - public Builder params(MessageSendParams params) { - this.params = params; - return this; - } - - /** - * Builds the {@link SendStreamingMessageRequest}. - * - * @return a new streaming message request instance - */ - public SendStreamingMessageRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new SendStreamingMessageRequest(jsonrpc, id, params); - } - } - } diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageResponse.java deleted file mode 100644 index 7cb428654..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageResponse.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.A2AError; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; - -/** - * JSON-RPC response for streaming message initiation requests. - *

- * This response is sent after receiving a {@link SendStreamingMessageRequest} and contains - * a stream of {@link StreamingEventKind} events representing the agent's processing progress. - * Unlike non-streaming responses, this provides real-time updates as the agent works. - *

- * The result field contains events such as {@link Task}, {@link TaskStatusUpdateEvent}, - * {@link TaskArtifactUpdateEvent}, and {@link Message} as they are produced by the agent. - *

- * If an error occurs during request processing, the error field will be populated with - * a {@link A2AError} instead of streaming events. - * - * @see SendStreamingMessageRequest for the corresponding request - * @see StreamingEventKind for the types of events that can be streamed - * @see A2A Protocol Specification - */ -public final class SendStreamingMessageResponse extends A2AResponse { - - /** - * Constructs response with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param result the result - * @param error the error if any - */ - public SendStreamingMessageResponse(String jsonrpc, Object id, StreamingEventKind result, A2AError error) { - super(jsonrpc, id, result, error, StreamingEventKind.class); - } - - /** - * Constructs successful response. - * - * @param id the request ID - * @param result the result - */ - public SendStreamingMessageResponse(Object id, StreamingEventKind result) { - this(null, id, result, null); - } - - /** - * Constructs error response. - * - * @param id the request ID - * @param error the error - */ - public SendStreamingMessageResponse(Object id, A2AError error) { - this(null, id, null, error); - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java deleted file mode 100644 index c55200847..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import io.a2a.spec.StreamingEventKind; - -/** - * Base class for JSON-RPC requests that support streaming responses in the A2A Protocol. - *

- * This sealed class extends {@link A2ARequest} to provide specialized support for - * A2A Protocol methods that return streaming responses. Streaming requests enable - * server-sent events and real-time updates to be pushed to clients as they occur, - * rather than waiting for a complete response. - *

- * The A2A Protocol defines two primary streaming operations: - *

    - *
  • {@link SendStreamingMessageRequest} - Stream task execution events in real-time
  • - *
  • {@link SubscribeToTaskRequest} - Subscribe to events from an existing task
  • - *
- *

- * Streaming requests follow the JSON-RPC 2.0 specification structure but the response - * is delivered as a stream of {@link StreamingEventKind} objects rather than a single - * response message. - *

- * This class uses a custom deserializer to properly handle polymorphic deserialization - * of streaming request types. - * - * @param the type of the params object for this streaming request - * @see SendStreamingMessageRequest - * @see SubscribeToTaskRequest - * @see StreamingEventKind - * @see A2A Protocol Specification - */ -public abstract sealed class StreamingJSONRPCRequest extends A2ARequest permits SubscribeToTaskRequest, - SendStreamingMessageRequest { - - StreamingJSONRPCRequest(String jsonrpc, String method, Object id, T params) { - validateAndSetJsonParameters(jsonrpc, method, id, params, true); - } - -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java deleted file mode 100644 index 1c965d5b1..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java +++ /dev/null @@ -1,121 +0,0 @@ -package io.a2a.jsonrpc.common.wrappers; - -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; - -import java.util.UUID; - -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskIdParams; - -/** - * JSON-RPC request to subscribe to an ongoing or completed task's event stream. - *

- * This request allows clients to reconnect to a task and receive its events, enabling - * recovery from disconnections or retrieval of missed updates. The agent will stream - * events for the task starting from its current state. - *

- * Resubscription is particularly useful for: - *

    - *
  • Recovering from network interruptions without losing task context
  • - *
  • Multiple clients observing the same task
  • - *
  • Retrieving final results for completed tasks
  • - *
- *

- * This class implements the JSON-RPC {@code SubscribeToTask} method as specified in the A2A Protocol. - * - * @see TaskIdParams for the parameter structure - * @see StreamingEventKind for the types of events that can be streamed - * @see A2A Protocol Specification - */ -public final class SubscribeToTaskRequest extends StreamingJSONRPCRequest { - - /** - * Constructs request with all parameters. - * - * @param jsonrpc the JSON-RPC version - * @param id the request ID - * @param params the request parameters - */ - public SubscribeToTaskRequest(String jsonrpc, Object id, TaskIdParams params) { - super(jsonrpc, SUBSCRIBE_TO_TASK_METHOD, id == null ? UUID.randomUUID().toString() : id, params); - } - - /** - * Constructs request with ID and parameters. - * - * @param id the request ID - * @param params the request parameters - */ - public SubscribeToTaskRequest(Object id, TaskIdParams params) { - this(null, id, params); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private String jsonrpc; - private Object id; - private TaskIdParams params; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the JSON-RPC version. - * - * @param jsonrpc the JSON-RPC version - * @return this builder for method chaining - */ - public SubscribeToTaskRequest.Builder jsonrpc(String jsonrpc) { - this.jsonrpc = jsonrpc; - return this; - } - - /** - * Sets the request ID. - * - * @param id the request ID - * @return this builder for method chaining - */ - public SubscribeToTaskRequest.Builder id(Object id) { - this.id = id; - return this; - } - - /** - * Sets the request parameters. - * - * @param params the request parameters - * @return this builder for method chaining - */ - public SubscribeToTaskRequest.Builder params(TaskIdParams params) { - this.params = params; - return this; - } - - /** - * Builds the instance. - * - * @return a new instance - */ - public SubscribeToTaskRequest build() { - if (id == null) { - id = UUID.randomUUID().toString(); - } - return new SubscribeToTaskRequest(jsonrpc, id, params); - } - } -} diff --git a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/package-info.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/package-info.java deleted file mode 100644 index 2de88b1f1..000000000 --- a/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/package-info.java +++ /dev/null @@ -1,14 +0,0 @@ -/** - * JSON-RPC 2.0 protocol message wrappers for the A2A Protocol. - *

- * This package contains internal implementation classes that wrap A2A Protocol domain objects - * in JSON-RPC 2.0 message structures. These classes are used by JSON-RPC transport implementations - * and are not part of the public SDK API. - *

- * Internal Use Only: Classes in this package are implementation details. - * The public API is in {@code io.a2a.spec}. - * - * @see io.a2a.spec - * @see JSON-RPC 2.0 Specification - */ -package io.a2a.jsonrpc.common.wrappers; diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java deleted file mode 100644 index ff7ee5cc1..000000000 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; - -import java.util.List; - -import io.a2a.spec.A2AError; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.UnsupportedOperationError; -import org.junit.jupiter.api.Test; - - -public class A2AErrorSerializationTest { - @Test - public void shouldDeserializeToCorrectA2AErrorSubclass() throws JsonProcessingException { - String jsonTemplate = """ - {"code": %s, "message": "error", "data": "anything"} - """; - - record ErrorCase(int code, Class clazz) {} - - List cases = List.of(new ErrorCase(JSON_PARSE_ERROR_CODE, JSONParseError.class), - new ErrorCase(INVALID_REQUEST_ERROR_CODE, InvalidRequestError.class), - new ErrorCase(METHOD_NOT_FOUND_ERROR_CODE, MethodNotFoundError.class), - new ErrorCase(INVALID_PARAMS_ERROR_CODE, InvalidParamsError.class), - new ErrorCase(INTERNAL_ERROR_CODE, InternalError.class), - new ErrorCase(PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE, PushNotificationNotSupportedError.class), - new ErrorCase(UNSUPPORTED_OPERATION_ERROR_CODE, UnsupportedOperationError.class), - new ErrorCase(CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE, ContentTypeNotSupportedError.class), - new ErrorCase(INVALID_AGENT_RESPONSE_ERROR_CODE, InvalidAgentResponseError.class), - new ErrorCase(TASK_NOT_CANCELABLE_ERROR_CODE, TaskNotCancelableError.class), - new ErrorCase(TASK_NOT_FOUND_ERROR_CODE, TaskNotFoundError.class), - new ErrorCase(Integer.MAX_VALUE, A2AError.class) // Any unknown code will be treated as A2AError - ); - - for (ErrorCase errorCase : cases) { - String json = jsonTemplate.formatted(errorCase.code()); - A2AError error = JsonUtil.fromJson(json, A2AError.class); - assertInstanceOf(errorCase.clazz(), error); - assertEquals("error", error.getMessage()); - assertEquals("anything", error.getData().toString()); - } - } - - -} diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java deleted file mode 100644 index b71809367..000000000 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecurityRequirementSerializationTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import static java.util.Collections.emptyMap; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.util.List; - -import org.junit.jupiter.api.Test; - -import io.a2a.spec.SecurityRequirement; - -/** - * Tests for SecurityRequirement serialization and deserialization with JSON. - */ -class SecurityRequirementSerializationTest { - - @Test - void testSecurityRequirementSerializationWithSingleScheme() throws JsonProcessingException { - SecurityRequirement requirement = SecurityRequirement.builder() - .scheme("oauth2", List.of("read", "write")) - .build(); - - String json = JsonUtil.toJson(requirement); - assertNotNull(json); - - String expected = """ - {"schemes":{"oauth2":{"list":["read","write"]}}}"""; - assertEquals(expected, json); - - SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); - assertEquals(requirement, deserialized); - } - - @Test - void testSecurityRequirementSerializationWithMultipleSchemes() throws JsonProcessingException { - SecurityRequirement requirement = SecurityRequirement.builder() - .scheme("oauth2", List.of("profile")) - .scheme("apiKey", List.of()) - .build(); - - String json = JsonUtil.toJson(requirement); - assertNotNull(json); - - String expected = """ - {"schemes":{"oauth2":{"list":["profile"]},"apiKey":{"list":[]}}}"""; - assertEquals(expected, json); - - SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); - assertEquals(requirement, deserialized); - } - - @Test - void testSecurityRequirementSerializationWithEmptyScopes() throws JsonProcessingException { - SecurityRequirement requirement = SecurityRequirement.builder() - .scheme("apiKey", List.of()) - .build(); - - String json = JsonUtil.toJson(requirement); - assertNotNull(json); - - String expected = """ - {"schemes":{"apiKey":{"list":[]}}}"""; - assertEquals(expected, json); - - SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); - assertEquals(requirement, deserialized); - } - - @Test - void testSecurityRequirementSerializationWithNullSchemes() throws JsonProcessingException { - SecurityRequirement requirement = new SecurityRequirement(emptyMap()); - - String json = JsonUtil.toJson(requirement); - - assertNotNull(json); - String expected = """ - {"schemes":{}}"""; - assertEquals(expected, json); - - SecurityRequirement deserialized = JsonUtil.fromJson(json, SecurityRequirement.class); - assertNotNull(deserialized); - assertEquals(requirement, deserialized); - } -} diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java deleted file mode 100644 index 5a5f3d856..000000000 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/SecuritySchemeSerializationTest.java +++ /dev/null @@ -1,211 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import static io.a2a.spec.APIKeySecurityScheme.Location.COOKIE; -import static io.a2a.spec.APIKeySecurityScheme.Location.HEADER; -import static io.a2a.spec.APIKeySecurityScheme.Location.QUERY; -import static java.lang.String.format; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Map; - -import org.junit.jupiter.api.Test; - -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.MutualTLSSecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import io.a2a.spec.SecurityScheme; - -/** - * Tests for SecurityScheme serialization and deserialization using Gson. - */ -class SecuritySchemeSerializationTest { - - @Test - void testHTTPAuthSecuritySchemeSerialization() throws JsonProcessingException { - SecurityScheme scheme = HTTPAuthSecurityScheme.builder() - .scheme("basic") - .description("Basic HTTP authentication") - .build(); - - doTestSecuritySchemeSerialization(scheme, HTTPAuthSecurityScheme.TYPE, Map.of("scheme", "basic")); - - } - - @Test - void testHTTPAuthSecuritySchemeDeserialization() throws JsonProcessingException { - String json = """ - { - "httpAuthSecurityScheme" : { - "scheme": "basic" - } - }"""; - SecurityScheme securityScheme = JsonUtil.fromJson(json, SecurityScheme.class); - assertInstanceOf(HTTPAuthSecurityScheme.class, securityScheme); - HTTPAuthSecurityScheme scheme = (HTTPAuthSecurityScheme) securityScheme; - assertEquals("basic", scheme.scheme()); - assertNull(scheme.bearerFormat()); - } - - @Test - void testHTTPAuthSecuritySchemeWithBearerFormatSerialization() throws JsonProcessingException { - SecurityScheme scheme = HTTPAuthSecurityScheme.builder() - .scheme("bearer") - .bearerFormat("JWT") - .description("JWT bearer token authentication") - .build(); - - doTestSecuritySchemeSerialization(scheme, HTTPAuthSecurityScheme.TYPE, - Map.of("scheme", "bearer", - "bearerFormat", "JWT", - "description", "JWT bearer token authentication")); - } - - @Test - void testHTTPAuthSecuritySchemeWithBearerFormatDeserialization() throws JsonProcessingException { - String json = """ - { - "httpAuthSecurityScheme" : { - "scheme": "bearer", - "bearerFormat": "JWT", - "description": "JWT authentication" - } - }"""; - SecurityScheme securityScheme = JsonUtil.fromJson(json, SecurityScheme.class); - assertInstanceOf(HTTPAuthSecurityScheme.class, securityScheme); - HTTPAuthSecurityScheme scheme = (HTTPAuthSecurityScheme) securityScheme; - assertEquals("bearer", scheme.scheme()); - assertEquals("JWT", scheme.bearerFormat()); - assertEquals("JWT authentication", scheme.description()); - } - - - @Test - void testAPIKeySecuritySchemeSerialization() throws JsonProcessingException { - SecurityScheme scheme = APIKeySecurityScheme.builder() - .location(HEADER) - .name("bar") - .build(); - - doTestSecuritySchemeSerialization(scheme, APIKeySecurityScheme.TYPE, Map.of("location", "header", - "name", "bar")); - } - - @Test - void testAPIKeySecuritySchemeDeserialization() throws JsonProcessingException { - String json = """ - { - "apiKeySecurityScheme" : { - "location": "cookie", - "name": "bar" - } - }"""; - SecurityScheme securityScheme = JsonUtil.fromJson(json, SecurityScheme.class); - assertInstanceOf(APIKeySecurityScheme.class, securityScheme); - APIKeySecurityScheme scheme = (APIKeySecurityScheme) securityScheme; - assertEquals(COOKIE, scheme.location()); - assertEquals("bar", scheme.name()); - } - - @Test - void testAPIKeySecuritySchemeWithDescriptionSerialization() throws JsonProcessingException { - SecurityScheme scheme = APIKeySecurityScheme.builder() - .location(QUERY) - .name("api_key") - .description("API key authentication via query parameter") - .build(); - - doTestSecuritySchemeSerialization(scheme, APIKeySecurityScheme.TYPE, - Map.of("location", "query", - "name", "api_key", - "description", "API key authentication via query parameter")); - } - - @Test - void testOpenIdConnectSecuritySchemeSerialization() throws JsonProcessingException { - SecurityScheme scheme = OpenIdConnectSecurityScheme.builder() - .openIdConnectUrl("https://example.com/.well-known/openid-configuration") - .description("OpenID Connect authentication") - .build(); - - doTestSecuritySchemeSerialization(scheme, OpenIdConnectSecurityScheme.TYPE, - Map.of("openIdConnectUrl", "https://example.com/.well-known/openid-configuration", - "description", "OpenID Connect authentication")); - } - - @Test - void testOpenIdConnectSecuritySchemeDeserialization() throws JsonProcessingException { - String json = """ - { - "openIdConnectSecurityScheme" : { - "openIdConnectUrl": "https://example.com/.well-known/openid-configuration", - "description": "OIDC authentication" - } - }"""; - - SecurityScheme securityScheme = JsonUtil.fromJson(json, SecurityScheme.class); - assertInstanceOf(OpenIdConnectSecurityScheme.class, securityScheme); - OpenIdConnectSecurityScheme scheme = (OpenIdConnectSecurityScheme) securityScheme; - assertEquals("https://example.com/.well-known/openid-configuration", scheme.openIdConnectUrl()); - assertEquals("OIDC authentication", scheme.description()); - } - - @Test - void testMutualTLSSecuritySchemeSerialization() throws JsonProcessingException { - SecurityScheme scheme = new MutualTLSSecurityScheme("Client certificate authentication required"); - - doTestSecuritySchemeSerialization(scheme, MutualTLSSecurityScheme.TYPE, - Map.of("description", "Client certificate authentication required")); - } - - @Test - void testMutualTLSSecuritySchemeDeserialization() throws JsonProcessingException { - String json = """ - { - "mtlsSecurityScheme" : { - "description": "mTLS authentication" - } - }"""; - - SecurityScheme securityScheme = JsonUtil.fromJson(json, SecurityScheme.class); - assertInstanceOf(MutualTLSSecurityScheme.class, securityScheme); - MutualTLSSecurityScheme scheme = (MutualTLSSecurityScheme) securityScheme; - assertEquals("mTLS authentication", scheme.description()); - } - - @Test - void testMutualTLSSecuritySchemeWithNullDescriptionDeserialization() throws JsonProcessingException { - String json = """ - { - "mtlsSecurityScheme" : { - } - }"""; - - SecurityScheme securityScheme = JsonUtil.fromJson(json, SecurityScheme.class); - assertInstanceOf(MutualTLSSecurityScheme.class, securityScheme); - MutualTLSSecurityScheme scheme = (MutualTLSSecurityScheme) securityScheme; - assertNull(scheme.description()); - } - - void doTestSecuritySchemeSerialization(SecurityScheme scheme, String schemeType, Map expectedFields) throws JsonProcessingException { - // Serialize to JSON - String json = JsonUtil.toJson(scheme); - - // Verify JSON contains expected fields - assertNotNull(json); - assertTrue(json.contains(schemeType)); - for (Map.Entry entry : expectedFields.entrySet()) { - String expectedField = format("\"%s\":\"%s\"", entry.getKey(), entry.getValue()); - assertTrue(json.contains(expectedField), expectedField + " not found in JSON"); - } - - // Deserialize back to Task - SecurityScheme deserialized = JsonUtil.fromJson(json, SecurityScheme.class); - - assertEquals(scheme, deserialized); - } -} \ No newline at end of file diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java deleted file mode 100644 index d0bf98090..000000000 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java +++ /dev/null @@ -1,263 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; - -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; - -/** - * Tests for StreamingEventKind serialization and deserialization. - *

- * Verifies that StreamingEventKind types (Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent) - * serialize using wrapper member names (e.g., {"task": {...}}) and do not contain "kind" fields. - */ -class StreamingEventKindSerializationTest { - - @Test - void testTaskSerialization() throws JsonProcessingException { - // Create a Task - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - // Serialize as StreamingEventKind - String json = JsonUtil.toJson((StreamingEventKind) task); - - // Verify JSON contains task wrapper, not "kind" field - assertNotNull(json); - assertTrue(json.contains("\"task\"")); - assertTrue(json.contains("\"id\":\"task-123\"")); - assertTrue(json.contains("\"state\":\"TASK_STATE_SUBMITTED\"")); - assertFalse(json.contains("\"kind\"")); - - // Deserialize back to StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Verify it's a Task - assertInstanceOf(Task.class, deserialized); - Task deserializedTask = (Task) deserialized; - assertEquals(task.id(), deserializedTask.id()); - assertEquals(task.contextId(), deserializedTask.contextId()); - assertEquals(task.status().state(), deserializedTask.status().state()); - } - - @Test - void testMessageSerialization() throws JsonProcessingException { - // Create a Message - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("Hello, agent!"))) - .taskId("task-789") - .messageId("msg-123") - .contextId("context-456") - .build(); - - // Serialize as StreamingEventKind - String json = JsonUtil.toJson((StreamingEventKind) message); - - // Verify JSON contains message wrapper, not "kind" field - assertNotNull(json); - assertTrue(json.contains("\"message\"")); - assertTrue(json.contains("\"taskId\":\"task-789\"")); - assertTrue(json.contains("\"role\":\"ROLE_USER\"")); - assertTrue(json.contains("Hello, agent!")); - assertFalse(json.contains("\"kind\"")); - - // Deserialize back to StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Verify it's a Message - assertInstanceOf(Message.class, deserialized); - Message deserializedMessage = (Message) deserialized; - assertEquals(message.taskId(), deserializedMessage.taskId()); - assertEquals(message.role(), deserializedMessage.role()); - assertEquals(message.parts().size(), deserializedMessage.parts().size()); - } - - @Test - void testTaskStatusUpdateEventSerialization() throws JsonProcessingException { - // Create a TaskStatusUpdateEvent - TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() - .taskId("task-abc") - .contextId("context-def") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - // Serialize as StreamingEventKind - String json = JsonUtil.toJson((StreamingEventKind) statusEvent); - - // Verify JSON contains statusUpdate wrapper, not "kind" field - assertNotNull(json); - assertTrue(json.contains("\"statusUpdate\"")); - assertTrue(json.contains("\"taskId\":\"task-abc\"")); - assertTrue(json.contains("\"state\":\"TASK_STATE_WORKING\"")); - assertTrue(json.contains("\"final\":false")); - assertFalse(json.contains("\"kind\"")); - - // Deserialize back to StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Verify it's a TaskStatusUpdateEvent - assertInstanceOf(TaskStatusUpdateEvent.class, deserialized); - TaskStatusUpdateEvent deserializedEvent = (TaskStatusUpdateEvent) deserialized; - assertEquals(statusEvent.taskId(), deserializedEvent.taskId()); - assertEquals(statusEvent.status().state(), deserializedEvent.status().state()); - assertEquals(statusEvent.isFinal(), deserializedEvent.isFinal()); - } - - @Test - void testTaskArtifactUpdateEventSerialization() throws JsonProcessingException { - // Create a TaskArtifactUpdateEvent - Artifact artifact = Artifact.builder() - .artifactId("artifact-xyz") - .name("Test Artifact") - .parts(List.of(new TextPart("Artifact content"))) - .build(); - - TaskArtifactUpdateEvent artifactEvent = TaskArtifactUpdateEvent.builder() - .taskId("task-123") - .contextId("context-456") - .artifact(artifact) - .build(); - - // Serialize as StreamingEventKind - String json = JsonUtil.toJson((StreamingEventKind) artifactEvent); - - // Verify JSON contains artifactUpdate wrapper, not "kind" field - assertNotNull(json); - assertTrue(json.contains("\"artifactUpdate\"")); - assertTrue(json.contains("\"taskId\":\"task-123\"")); - assertTrue(json.contains("\"artifactId\":\"artifact-xyz\"")); - assertTrue(json.contains("Artifact content")); - assertFalse(json.contains("\"kind\"")); - - // Deserialize back to StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Verify it's a TaskArtifactUpdateEvent - assertInstanceOf(TaskArtifactUpdateEvent.class, deserialized); - TaskArtifactUpdateEvent deserializedEvent = (TaskArtifactUpdateEvent) deserialized; - assertEquals(artifactEvent.taskId(), deserializedEvent.taskId()); - assertEquals(artifactEvent.artifact().artifactId(), deserializedEvent.artifact().artifactId()); - } - - @Test - void testUnwrappedTaskDeserialization() throws JsonProcessingException { - // Test that unwrapped Task format (direct deserialization) still works - String json = """ - { - "id": "task-unwrapped", - "contextId": "context-999", - "status": { - "state": "TASK_STATE_COMPLETED" - } - } - """; - - // Deserialize as StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Should successfully deserialize as Task - assertInstanceOf(Task.class, deserialized); - Task task = (Task) deserialized; - assertEquals("task-unwrapped", task.id()); - assertEquals("context-999", task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - } - - @Test - void testUnwrappedMessageDeserialization() throws JsonProcessingException { - // Test that unwrapped Message format (direct deserialization) still works - String json = """ - { - "role": "ROLE_AGENT", - "parts": [ - { - "text": "Unwrapped message" - } - ], - "messageId": "msg-unwrapped", - "taskId": "task-999" - } - """; - - // Deserialize as StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Should successfully deserialize as Message - assertInstanceOf(Message.class, deserialized); - Message message = (Message) deserialized; - assertEquals("msg-unwrapped", message.messageId()); - assertEquals("task-999", message.taskId()); - assertEquals(Message.Role.ROLE_AGENT, message.role()); - } - - @Test - void testUnwrappedTaskStatusUpdateEventDeserialization() throws JsonProcessingException { - // Test that unwrapped TaskStatusUpdateEvent format still works - String json = """ - { - "taskId": "task-status-unwrapped", - "contextId": "context-999", - "status": { - "state": "TASK_STATE_WORKING" - }, - "final": false - } - """; - - // Deserialize as StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Should successfully deserialize as TaskStatusUpdateEvent - assertInstanceOf(TaskStatusUpdateEvent.class, deserialized); - TaskStatusUpdateEvent event = (TaskStatusUpdateEvent) deserialized; - assertEquals("task-status-unwrapped", event.taskId()); - assertEquals(TaskState.TASK_STATE_WORKING, event.status().state()); - assertFalse(event.isFinal()); - } - - @Test - void testUnwrappedTaskArtifactUpdateEventDeserialization() throws JsonProcessingException { - // Test that unwrapped TaskArtifactUpdateEvent format still works - String json = """ - { - "taskId": "task-artifact-unwrapped", - "contextId": "context-999", - "artifact": { - "artifactId": "artifact-unwrapped", - "parts": [ - { - "text": "Unwrapped artifact" - } - ] - } - } - """; - - // Deserialize as StreamingEventKind - StreamingEventKind deserialized = JsonUtil.fromJson(json, StreamingEventKind.class); - - // Should successfully deserialize as TaskArtifactUpdateEvent - assertInstanceOf(TaskArtifactUpdateEvent.class, deserialized); - TaskArtifactUpdateEvent event = (TaskArtifactUpdateEvent) deserialized; - assertEquals("task-artifact-unwrapped", event.taskId()); - assertEquals("artifact-unwrapped", event.artifact().artifactId()); - } -} diff --git a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java deleted file mode 100644 index 9c0fd2610..000000000 --- a/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java +++ /dev/null @@ -1,713 +0,0 @@ -package io.a2a.jsonrpc.common.json; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.time.OffsetDateTime; -import java.util.List; -import java.util.Map; - -import io.a2a.spec.Artifact; -import io.a2a.spec.DataPart; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; - -/** - * Tests for Task serialization and deserialization using Gson. - */ -class TaskSerializationTest { - - @Test - void testBasicTaskSerialization() throws JsonProcessingException { - // Create a basic task - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - // Serialize to JSON - String json = JsonUtil.toJson(task); - - // Verify JSON contains expected fields - assertNotNull(json); - assertTrue(json.contains("\"id\":\"task-123\"")); - assertTrue(json.contains("\"state\":\"TASK_STATE_SUBMITTED\"")); - - // Deserialize back to Task - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify deserialized task matches original - assertEquals(task.id(), deserialized.id()); - assertEquals(task.status().state(), deserialized.status().state()); - } - - @Test - void testTaskWithTimestamp() throws JsonProcessingException { - OffsetDateTime timestamp = OffsetDateTime.now(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify OffsetDateTime timestamp is preserved - assertNotNull(deserialized.status().timestamp()); - assertEquals(task.status().timestamp(), deserialized.status().timestamp()); - } - - @Test - void testTaskWithArtifacts() throws JsonProcessingException { - Artifact artifact = Artifact.builder() - .artifactId("artifact-1") - .name("Test Artifact") - .description("Description of artifact") - .parts(List.of( - new TextPart("Hello"), - new TextPart("World") - )) - .build(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .artifacts(List.of(artifact)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Verify JSON contains artifact data - assertTrue(json.contains("\"artifactId\":\"artifact-1\"")); - assertTrue(json.contains("Hello")); - assertTrue(json.contains("World")); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify artifacts are preserved - assertNotNull(deserialized.artifacts()); - assertEquals(1, deserialized.artifacts().size()); - assertEquals("artifact-1", deserialized.artifacts().get(0).artifactId()); - assertEquals(2, deserialized.artifacts().get(0).parts().size()); - } - - @Test - void testTaskWithHistory() throws JsonProcessingException { - Message message = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("Test message"))) - .build(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .history(List.of(message)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Verify JSON contains history data - assertTrue(json.contains("\"role\":\"ROLE_USER\"")); - assertTrue(json.contains("Test message")); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify history is preserved - assertNotNull(deserialized.history()); - assertEquals(1, deserialized.history().size()); - assertEquals(Message.Role.ROLE_USER, deserialized.history().get(0).role()); - assertEquals(1, deserialized.history().get(0).parts().size()); - } - - @Test - void testTaskWithAllFields() throws JsonProcessingException { - OffsetDateTime timestamp = OffsetDateTime.now(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-789") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) - .history(List.of( - Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart("User message"))) - .build(), - Message.builder() - .role(Message.Role.ROLE_AGENT) - .parts(List.of(new TextPart("Agent response"))) - .build() - )) - .artifacts(List.of( - Artifact.builder() - .artifactId("artifact-1") - .parts(List.of(new TextPart("Artifact content"))) - .build() - )) - .metadata(Map.of("key1", "value1", "key2", 42)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify all fields are preserved - assertEquals(task.id(), deserialized.id()); - assertEquals(task.contextId(), deserialized.contextId()); - assertEquals(task.status().state(), deserialized.status().state()); - assertEquals(task.status().timestamp(), deserialized.status().timestamp()); - assertEquals(task.history().size(), deserialized.history().size()); - assertEquals(task.artifacts().size(), deserialized.artifacts().size()); - assertNotNull(deserialized.metadata()); - assertEquals("value1", deserialized.metadata().get("key1")); - } - - @Test - void testTaskWithDifferentStates() throws JsonProcessingException { - for (TaskState state : TaskState.values()) { - Task task = Task.builder() - .id("task-" + state) - .contextId("context-123") - .status(new TaskStatus(state)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Verify state is serialized correctly - assertTrue(json.contains("\"state\":\"" + state + "\"")); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify state is preserved - assertEquals(state, deserialized.status().state()); - } - } - - @Test - void testTaskWithNullOptionalFields() throws JsonProcessingException { - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - // artifacts, history, metadata not set - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify required fields are present - assertEquals("task-123", deserialized.id()); - assertEquals("context-456", deserialized.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, deserialized.status().state()); - - // Verify optional lists default to empty - assertNotNull(deserialized.artifacts()); - assertEquals(0, deserialized.artifacts().size()); - assertNotNull(deserialized.history()); - assertEquals(0, deserialized.history().size()); - } - - @Test - void testTaskWithFilePartBytes() throws JsonProcessingException { - FilePart filePart = new FilePart(new FileWithBytes("application/pdf", "document.pdf", "base64data")); - - Artifact artifact = Artifact.builder() - .artifactId("file-artifact") - .parts(List.of(filePart)) - .build(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .artifacts(List.of(artifact)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Verify JSON contains file part data (v1.0 format uses member name "file", not "kind") - assertTrue(json.contains("\"file\"")); - assertFalse(json.contains("\"kind\"")); - assertTrue(json.contains("document.pdf")); - assertTrue(json.contains("application/pdf")); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify file part is preserved - Part part = deserialized.artifacts().get(0).parts().get(0); - assertTrue(part instanceof FilePart); - FilePart deserializedFilePart = (FilePart) part; - assertTrue(deserializedFilePart.file() instanceof FileWithBytes); - FileWithBytes fileWithBytes = (FileWithBytes) deserializedFilePart.file(); - assertEquals("document.pdf", fileWithBytes.name()); - assertEquals("application/pdf", fileWithBytes.mimeType()); - } - - @Test - void testTaskWithFilePartUri() throws JsonProcessingException { - FilePart filePart = new FilePart(new FileWithUri("image/png", "photo.png", "https://example.com/photo.png")); - - Artifact artifact = Artifact.builder() - .artifactId("uri-artifact") - .parts(List.of(filePart)) - .build(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .artifacts(List.of(artifact)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Verify JSON contains URI - assertTrue(json.contains("https://example.com/photo.png")); - assertFalse(json.contains("\"kind\"")); // Removed in spec 1.0 - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify file part URI is preserved - Part part = deserialized.artifacts().get(0).parts().get(0); - assertTrue(part instanceof FilePart); - FilePart deserializedFilePart = (FilePart) part; - assertTrue(deserializedFilePart.file() instanceof FileWithUri); - FileWithUri fileWithUri = (FileWithUri) deserializedFilePart.file(); - assertEquals("https://example.com/photo.png", fileWithUri.uri()); - } - - @Test - void testTaskWithDataPart() throws JsonProcessingException { - DataPart dataPart = new DataPart(Map.of("temperature", 22.5, "humidity", 65)); - - Artifact artifact = Artifact.builder() - .artifactId("data-artifact") - .parts(List.of(dataPart)) - .build(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .artifacts(List.of(artifact)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Verify JSON contains data part (v1.0 format uses member name "data", not "kind") - assertTrue(json.contains("\"data\"")); - assertFalse(json.contains("\"kind\"")); - assertTrue(json.contains("temperature")); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify data part is preserved - Part part = deserialized.artifacts().get(0).parts().get(0); - assertTrue(part instanceof DataPart); - DataPart deserializedDataPart = (DataPart) part; - assertNotNull(deserializedDataPart.data()); - } - - @Test - void testTaskRoundTrip() throws JsonProcessingException { - // Create a comprehensive task with all part types - OffsetDateTime timestamp = OffsetDateTime.now(); - - Task original = Task.builder() - .id("task-123") - .contextId("context-789") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING, null, timestamp)) - .history(List.of( - Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of( - new TextPart("Text"), - new FilePart(new FileWithBytes("text/plain", "file.txt", "data")), - new DataPart(Map.of("key", "value")) - )) - .build() - )) - .artifacts(List.of( - Artifact.builder() - .artifactId("artifact-1") - .parts(List.of(new TextPart("Content"))) - .build() - )) - .metadata(Map.of("meta1", "value1")) - .build(); - - // Serialize to JSON - String json = JsonUtil.toJson(original); - - // Deserialize back to Task - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Serialize again - String json2 = JsonUtil.toJson(deserialized); - - // Deserialize again - Task deserialized2 = JsonUtil.fromJson(json2, Task.class); - - // Verify multiple round-trips produce identical results - assertEquals(deserialized.id(), deserialized2.id()); - assertEquals(deserialized.contextId(), deserialized2.contextId()); - assertEquals(deserialized.status().state(), deserialized2.status().state()); - assertEquals(deserialized.history().size(), deserialized2.history().size()); - assertEquals(deserialized.artifacts().size(), deserialized2.artifacts().size()); - } - - @Test - void testTaskStatusWithMessage() throws JsonProcessingException { - Message statusMessage = Message.builder() - .role(Message.Role.ROLE_AGENT) - .parts(List.of(new TextPart("Processing complete"))) - .build(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED, statusMessage, null)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Verify JSON contains status message - assertTrue(json.contains("\"state\":\"TASK_STATE_COMPLETED\"")); - assertTrue(json.contains("Processing complete")); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify status message is preserved - assertEquals(TaskState.TASK_STATE_COMPLETED, deserialized.status().state()); - assertNotNull(deserialized.status().message()); - assertEquals(Message.Role.ROLE_AGENT, deserialized.status().message().role()); - assertTrue(deserialized.status().message().parts().get(0) instanceof TextPart); - } - - @Test - void testDeserializeTaskFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_SUBMITTED" - } - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - assertEquals("context-456", task.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, task.status().state()); - assertNull(task.status().message()); - // TaskStatus automatically sets timestamp to current time if not provided - assertNotNull(task.status().timestamp()); - } - - @Test - void testDeserializeTaskWithArtifactsFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_COMPLETED" - }, - "artifacts": [ - { - "artifactId": "artifact-1", - "name": "Result", - "parts": [ - { - "text": "Hello World" - } - ] - } - ] - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - assertEquals(1, task.artifacts().size()); - assertEquals("artifact-1", task.artifacts().get(0).artifactId()); - assertEquals("Result", task.artifacts().get(0).name()); - assertEquals(1, task.artifacts().get(0).parts().size()); - assertTrue(task.artifacts().get(0).parts().get(0) instanceof TextPart); - assertEquals("Hello World", ((TextPart) task.artifacts().get(0).parts().get(0)).text()); - } - - @Test - void testDeserializeTaskWithFilePartBytesFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_COMPLETED" - }, - "artifacts": [ - { - "artifactId": "file-artifact", - "parts": [ - { - "file": { - "mimeType": "application/pdf", - "name": "document.pdf", - "bytes": "base64encodeddata" - } - } - ] - } - ] - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - assertEquals(1, task.artifacts().size()); - Part part = task.artifacts().get(0).parts().get(0); - assertTrue(part instanceof FilePart); - FilePart filePart = (FilePart) part; - assertTrue(filePart.file() instanceof FileWithBytes); - FileWithBytes fileWithBytes = (FileWithBytes) filePart.file(); - assertEquals("application/pdf", fileWithBytes.mimeType()); - assertEquals("document.pdf", fileWithBytes.name()); - assertEquals("base64encodeddata", fileWithBytes.bytes()); - } - - @Test - void testDeserializeTaskWithFilePartUriFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_COMPLETED" - }, - "artifacts": [ - { - "artifactId": "uri-artifact", - "parts": [ - { - "file": { - "mimeType": "image/png", - "name": "photo.png", - "uri": "https://example.com/photo.png" - } - } - ] - } - ] - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - Part part = task.artifacts().get(0).parts().get(0); - assertTrue(part instanceof FilePart); - FilePart filePart = (FilePart) part; - assertTrue(filePart.file() instanceof FileWithUri); - FileWithUri fileWithUri = (FileWithUri) filePart.file(); - assertEquals("image/png", fileWithUri.mimeType()); - assertEquals("photo.png", fileWithUri.name()); - assertEquals("https://example.com/photo.png", fileWithUri.uri()); - } - - @Test - void testDeserializeTaskWithDataPartFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_COMPLETED" - }, - "artifacts": [ - { - "artifactId": "data-artifact", - "parts": [ - { - "data": { - "temperature": 22.5, - "humidity": 65 - } - } - ] - } - ] - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - Part part = task.artifacts().get(0).parts().get(0); - assertTrue(part instanceof DataPart); - DataPart dataPart = (DataPart) part; - assertNotNull(dataPart.data()); - } - - @Test - void testDeserializeTaskWithHistoryFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_WORKING" - }, - "history": [ - { - "role": "ROLE_USER", - "parts": [ - { - "text": "User message" - } - ], - "messageId": "msg-1" - }, - { - "role": "ROLE_AGENT", - "parts": [ - { - "text": "Agent response" - } - ], - "messageId": "msg-2" - } - ] - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - assertEquals(2, task.history().size()); - assertEquals(Message.Role.ROLE_USER, task.history().get(0).role()); - assertEquals(Message.Role.ROLE_AGENT, task.history().get(1).role()); - assertTrue(task.history().get(0).parts().get(0) instanceof TextPart); - assertEquals("User message", ((TextPart) task.history().get(0).parts().get(0)).text()); - } - - @Test - void testDeserializeTaskWithTimestampFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_WORKING", - "timestamp": "2023-10-01T12:00:00.234-05:00" - } - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - assertEquals(TaskState.TASK_STATE_WORKING, task.status().state()); - assertNotNull(task.status().timestamp()); - assertEquals("2023-10-01T12:00:00.234-05:00", task.status().timestamp().toString()); - } - - @Test - void testDeserializeTaskWithMetadataFromJson() throws JsonProcessingException { - String json = """ - { - "id": "task-123", - "contextId": "context-456", - "status": { - "state": "TASK_STATE_COMPLETED" - }, - "metadata": { - "key1": "value1", - "key2": 42 - } - } - """; - - Task task = JsonUtil.fromJson(json, Task.class); - - assertEquals("task-123", task.id()); - assertNotNull(task.metadata()); - assertEquals("value1", task.metadata().get("key1")); - } - - @Test - void testTaskWithMixedPartTypes() throws JsonProcessingException { - Artifact artifact = Artifact.builder() - .artifactId("mixed-artifact") - .parts(List.of( - new TextPart("Text content"), - new FilePart(new FileWithBytes("application/json", "data.json", "{}")), - new DataPart(Map.of("result", 42)), - new FilePart(new FileWithUri("image/png", "image.png", "https://example.com/img.png")) - )) - .build(); - - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .artifacts(List.of(artifact)) - .build(); - - // Serialize - String json = JsonUtil.toJson(task); - - // Deserialize - Task deserialized = JsonUtil.fromJson(json, Task.class); - - // Verify all part types are preserved - List> parts = deserialized.artifacts().get(0).parts(); - assertEquals(4, parts.size()); - assertTrue(parts.get(0) instanceof TextPart); - assertTrue(parts.get(1) instanceof FilePart); - assertTrue(parts.get(2) instanceof DataPart); - assertTrue(parts.get(3) instanceof FilePart); - } -} diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 7b94e7b4b..000000000 --- a/pom.xml +++ /dev/null @@ -1,623 +0,0 @@ - - - 4.0.0 - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - pom - - Java SDK A2A Parent - Java SDK for the Agent2Agent Protocol (A2A) - - https://github.com/a2asdk/a2a-java-sdk - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - - a2a-java - The a2a-java developers - a2aproject - https://github.com/a2aproject/a2a-java - - - - - scm:git:git://github.com/a2asdk/a2a-java-sdk.git - scm:git:ssh://github.com:a2asdk/a2a-java-sdk.git - https://github.com/a2asdk/a2a-java-sdk - - - - - 1.77.0 - UTF-8 - 3.5.0 - 3.14.1 - 3.6.2 - 3.4.2 - 3.3.1 - 3.1.2 - 3.8.0 - 3.2.4 - 4.2.1 - 0.8.0 - 5.0.3 - 2.13.2 - 4.1.0 - 2.0.1 - 2.1.3 - 3.1.0 - 5.13.4 - 1.6.3 - 1.52.0 - 5.17.0 - 5.15.0 - 1.1.1 - 1.7.1 - 4.33.1 - 0.6.1 - 3.30.6 - 5.5.1 - 2.0.17 - 1.5.18 - 1.21.4 - 2.47.0 - 0.13.1 - -XDaddTypeAnnotationsToSymbol=true - -Xplugin:ErrorProne -XepDisableAllChecks -Xep:NullAway:ERROR -Xep:RequireExplicitNullMarking:WARN -XepOpt:NullAway:ExhaustiveOverride=true -XepOpt:NullAway:OnlyNullMarked=true -XepOpt:NullAway:JSpecifyMode=true -XepExcludedPaths:.*/src/test/.* -XepDisableWarningsInGeneratedCode - - - true - --add-opens=java.base/java.lang=ALL-UNNAMED - - - false - - - - - - ${project.groupId} - a2a-java-sdk-client - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-spi - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-jsonrpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-client-transport-rest - ${project.version} - - - ${project.groupId} - a2a-java-sdk-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-http-client - ${project.version} - - - ${project.groupId} - a2a-java-sdk-http-client-vertx - ${project.version} - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-spec - ${project.version} - - - ${project.groupId} - a2a-java-sdk-spec-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-server-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-microprofile-config - ${project.version} - - - ${project.groupId} - a2a-java-extras-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-transport-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-transport-jsonrpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-transport-rest - ${project.version} - - - ${project.groupId} - a2a-java-sdk-reference-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-reference-grpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-reference-jsonrpc - ${project.version} - - - ${project.groupId} - a2a-java-sdk-reference-rest - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-opentelemetry - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-spring - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-common - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-client - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-server - ${project.version} - - - io.github.a2asdk - a2a-java-sdk-opentelemetry-client-propagation - ${project.version} - - - io.grpc - grpc-bom - ${grpc.version} - pom - import - - - org.testcontainers - testcontainers-bom - ${version.testcontainers} - pom - import - - - io.quarkus - quarkus-bom - ${quarkus.platform.version} - pom - import - - - org.slf4j - slf4j-bom - ${slf4j.version} - pom - import - - - com.google.protobuf - protobuf-java - ${protobuf-java.version} - - - com.google.code.gson - gson - - - - - com.google.code.gson - gson - ${gson.version} - - - io.smallrye.reactive - mutiny-zero - ${mutiny-zero.version} - - - jakarta.enterprise - jakarta.enterprise.cdi-api - ${jakarta.enterprise.cdi-api.version} - - - jakarta.inject - jakarta.inject-api - ${jakarta.inject.jakarta.inject-api.version} - - - org.mapstruct - mapstruct - ${mapstruct.version} - - - org.mapstruct - mapstruct-processor - ${mapstruct.version} - - - jakarta.json - jakarta.json-api - ${jakarta.json-api.version} - provided - - - jakarta.ws.rs - jakarta.ws.rs-api - ${jakarta.ws.rs-api.version} - provided - - - org.junit.jupiter - junit-jupiter-api - ${junit.version} - test - - - io.rest-assured - rest-assured - ${rest-assured.version} - test - - - org.mockito - mockito-core - ${mockito-core.version} - test - - - org.mock-server - mockserver-netty - ${mockserver.version} - test - - - ch.qos.logback - logback-classic - ${logback.version} - test - - - ${project.groupId} - a2a-java-sdk-tests-server-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-tests-server-common - test-jar - test - ${project.version} - - - ${project.groupId} - a2a-java-sdk-server-common - test-jar - test - ${project.version} - - - org.jspecify - jspecify - 1.0.0 - provided - - - - - - - org.jspecify - jspecify - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 17 - 17 - 17 - UTF-8 - true - - -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED - -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED - -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED - -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED - -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED - -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED - -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED - -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED - -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED - -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED - -XDcompilePolicy=simple - --should-stop=ifError=FLOW - -parameters - ${error-prone.flag} - ${nullaway.args} - - - - com.google.errorprone - error_prone_core - ${error-prone.version} - - - com.uber.nullaway - nullaway - ${nullaway.version} - - - org.mapstruct - mapstruct-processor - ${mapstruct.version} - - - no.entur.mapstruct.spi - protobuf-spi-impl - ${mapstruct-spi-protobuf.version} - - - - - - - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - ${maven.home} - - - - - org.codehaus.gmavenplus - gmavenplus-plugin - ${gmavenplus-plugin.version} - - - org.apache.groovy - groovy - ${groovy.version} - runtime - - - org.apache.groovy - groovy-ant - ${groovy.version} - runtime - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 - - - io.quarkus - quarkus-maven-plugin - true - ${quarkus.platform.version} - - ${quarkus.jvm.args} - - - - org.sonatype.central - central-publishing-maven-plugin - ${sonatype-central-publishing-plugin.version} - true - - - central-a2asdk-temp - ${release.auto.publish} - - - - org.apache.maven.plugins - maven-source-plugin - ${maven-source-plugin.version} - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - ${maven-javadoc-plugin.version} - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - ${maven-gpg-plugin.version} - - - sign-artifacts - verify - - sign - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.sonatype.central - central-publishing-maven-plugin - - - - - - - boms/test-utils - - - client/base - client/transport/grpc - client/transport/jsonrpc - client/transport/rest - client/transport/spi - common - examples/helloworld - examples/cloud-deployment/server - extras/common - extras/opentelemetry - extras/task-store-database-jpa - extras/push-notification-config-store-database-jpa - extras/queue-manager-replicated - extras/http-client-vertx - http-client - jsonrpc-common - integrations/microprofile-config - reference/common - reference/grpc - reference/jsonrpc - reference/rest - server-common - spec - spec-grpc - tck - tests/server-common - transport/jsonrpc - transport/grpc - transport/rest - - - boms/extras - boms/reference - boms/sdk - - - - - - release - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-gpg-plugin - - - - - - - old_jdk_support - - (17, 21] - - - 2.42.0 - 0.12.10 - - -Xplugin:ErrorProne -XepDisableAllChecks -Xep:NullAway:ERROR -XepOpt:NullAway:OnlyNullMarked=true -XepOpt:NullAway:JSpecifyMode=true -XepExcludedPaths:.*/src/test/.* -XepDisableWarningsInGeneratedCode - - - - - - \ No newline at end of file diff --git a/reference/common/pom.xml b/reference/common/pom.xml deleted file mode 100644 index 1a88d7dd4..000000000 --- a/reference/common/pom.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-reference-common - - jar - - Java A2A Reference Server: Common - Java SDK for the Agent2Agent Protocol (A2A) - Common classes for A2A Reference Servers (based on Quarkus) - - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-tests-server-common - provided - - - ${project.groupId} - a2a-java-sdk-tests-server-common - test-jar - test - - - io.quarkus - quarkus-reactive-routes - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - org.slf4j - slf4j-api - - - ${project.groupId} - a2a-java-sdk-microprofile-config - - - io.quarkus - quarkus-junit5 - test - - - io.quarkus - quarkus-rest-client - test - - - org.junit.jupiter - junit-jupiter-api - test - - - io.rest-assured - rest-assured - test - - - \ No newline at end of file diff --git a/reference/common/src/main/java/io/a2a/server/common/quarkus/DefaultProducers.java b/reference/common/src/main/java/io/a2a/server/common/quarkus/DefaultProducers.java deleted file mode 100644 index cbc38f13f..000000000 --- a/reference/common/src/main/java/io/a2a/server/common/quarkus/DefaultProducers.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.a2a.server.common.quarkus; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import io.a2a.server.PublicAgentCard; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.spec.AgentCard; -import io.quarkus.arc.DefaultBean; - -/** - * Contains beans annotated with the Quarkus @DefaultBean annotation, in order to avoid - * injection failures when building the Quarkus application as discussed in - * Issue 213. - * - * If an application provides actual implementations of these beans, - * those will be used instead. - */ -@ApplicationScoped -public class DefaultProducers { - @Produces - @PublicAgentCard - @DefaultBean - public AgentCard createDefaultAgentCard() { - throw new IllegalStateException(wrap("Please provide your own AgentCard implementation")); - } - - @Produces - @DefaultBean - public AgentExecutor createDefaultAgentExecutor() { - throw new IllegalStateException(wrap("Please provide your own AgentExecutor implementation")); - } - - private String wrap(String s) { - return s + - " as a CDI bean. Your bean will automatically take precedence over this @DefaultBean " + - "annotated implementation."; - } -} diff --git a/reference/common/src/main/resources/META-INF/beans.xml b/reference/common/src/main/resources/META-INF/beans.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml deleted file mode 100644 index 50cf450c3..000000000 --- a/reference/grpc/pom.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - 4.0.0 - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - - a2a-java-sdk-reference-grpc - Java A2A Reference Server: gRPC - Java SDK for the Agent2Agent Protocol (A2A) - A2A gRPC Reference Server (based on Quarkus) - - - - ${project.groupId} - a2a-java-sdk-reference-common - - - ${project.groupId} - a2a-java-sdk-common - - - ${project.groupId} - a2a-java-sdk-transport-grpc - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-tests-server-common - provided - - - ${project.groupId} - a2a-java-sdk-tests-server-common - test-jar - test - - - ${project.groupId} - a2a-java-sdk-client-transport-grpc - test - - - - io.quarkus - quarkus-grpc - - - io.quarkus - quarkus-rest - test - - - io.quarkus - quarkus-junit5 - test - - - org.assertj - assertj-core - 3.25.3 - test - - - com.google.api.grpc - proto-google-common-protos - - - com.google.protobuf - protobuf-java - - - io.grpc - grpc-protobuf - - - io.grpc - grpc-stub - - - io.rest-assured - rest-assured - test - - - - \ No newline at end of file diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java deleted file mode 100644 index 3b0421b44..000000000 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java +++ /dev/null @@ -1,82 +0,0 @@ -package io.a2a.server.grpc.quarkus; - -import jakarta.enterprise.context.ApplicationScoped; - -import io.a2a.common.A2AHeaders; -import io.a2a.transport.grpc.context.GrpcContextKeys; -import io.grpc.Context; -import io.grpc.Contexts; -import io.grpc.Metadata; -import io.grpc.ServerCall; -import io.grpc.ServerCallHandler; -import io.grpc.ServerInterceptor; - -/** - * gRPC server interceptor that captures request metadata and context information, - * providing equivalent functionality to Python's grpc.aio.ServicerContext. - * - * This interceptor: - * - Extracts A2A extension headers from incoming requests - * - Captures ServerCall and Metadata for rich context access - * - Stores context information in gRPC Context for service method access - * - Provides proper equivalence to Python's ServicerContext - */ -@ApplicationScoped -public class A2AExtensionsInterceptor implements ServerInterceptor { - - @Override - public ServerCall.Listener interceptCall( - ServerCall serverCall, - Metadata metadata, - ServerCallHandler serverCallHandler) { - - // Extract A2A protocol version header - Metadata.Key versionKey = - Metadata.Key.of(A2AHeaders.X_A2A_VERSION, Metadata.ASCII_STRING_MARSHALLER); - String version = metadata.get(versionKey); - - // Extract A2A extensions header - Metadata.Key extensionsKey = - Metadata.Key.of(A2AHeaders.X_A2A_EXTENSIONS, Metadata.ASCII_STRING_MARSHALLER); - String extensions = metadata.get(extensionsKey); - - // Create enhanced context with rich information (equivalent to Python's ServicerContext) - Context context = Context.current() - // Store complete metadata for full header access - .withValue(GrpcContextKeys.METADATA_KEY, metadata) - // Store Grpc method name - .withValue(GrpcContextKeys.GRPC_METHOD_NAME_KEY, serverCall.getMethodDescriptor().getFullMethodName()) - // Store method name (equivalent to Python's context.method()) - .withValue(GrpcContextKeys.METHOD_NAME_KEY, GrpcContextKeys.METHOD_MAPPING.get(serverCall.getMethodDescriptor().getBareMethodName())) - // Store peer information for client connection details - .withValue(GrpcContextKeys.PEER_INFO_KEY, getPeerInfo(serverCall)); - - // Store A2A version if present - if (version != null) { - context = context.withValue(GrpcContextKeys.VERSION_HEADER_KEY, version); - } - - // Store A2A extensions if present - if (extensions != null) { - context = context.withValue(GrpcContextKeys.EXTENSIONS_HEADER_KEY, extensions); - } - - // Proceed with the call in the enhanced context - return Contexts.interceptCall(context, serverCall, metadata, serverCallHandler); - } - - /** - * Safely extracts peer information from the ServerCall. - * - * @param serverCall the gRPC ServerCall - * @return peer information string, or "unknown" if not available - */ - private String getPeerInfo(ServerCall serverCall) { - try { - Object remoteAddr = serverCall.getAttributes().get(io.grpc.Grpc.TRANSPORT_ATTR_REMOTE_ADDR); - return remoteAddr != null ? remoteAddr.toString() : "unknown"; - } catch (Exception e) { - return "unknown"; - } - } -} diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java deleted file mode 100644 index e5f7a27c2..000000000 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -package io.a2a.server.grpc.quarkus; - -import java.util.concurrent.Executor; - -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import io.a2a.server.ExtendedAgentCard; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.AgentCard; -import io.a2a.transport.grpc.handler.CallContextFactory; -import io.a2a.transport.grpc.handler.GrpcHandler; -import io.quarkus.grpc.GrpcService; -import io.quarkus.grpc.RegisterInterceptor; -import io.quarkus.security.Authenticated; -import org.jspecify.annotations.Nullable; - -@GrpcService -@RegisterInterceptor(A2AExtensionsInterceptor.class) -@Authenticated -public class QuarkusGrpcHandler extends GrpcHandler { - - private final AgentCard agentCard; - private final AgentCard extendedAgentCard; - private final RequestHandler requestHandler; - private final Instance callContextFactoryInstance; - private final Executor executor; - - /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. - */ - - @Inject - public QuarkusGrpcHandler(@PublicAgentCard AgentCard agentCard, - @ExtendedAgentCard Instance extendedAgentCard, - RequestHandler requestHandler, - Instance callContextFactoryInstance, - @Internal Executor executor) { - this.agentCard = agentCard; - if (extendedAgentCard != null && extendedAgentCard.isResolvable()) { - this.extendedAgentCard = extendedAgentCard.get(); - } else { - this.extendedAgentCard = null; - } - this.requestHandler = requestHandler; - this.callContextFactoryInstance = callContextFactoryInstance; - this.executor = executor; - } - - @Override - protected RequestHandler getRequestHandler() { - return requestHandler; - } - - @Override - protected AgentCard getAgentCard() { - return agentCard; - } - - @Override - protected AgentCard getExtendedAgentCard() { - return extendedAgentCard; - } - - @Override - protected CallContextFactory getCallContextFactory() { - return callContextFactoryInstance.isUnsatisfied() ? null : callContextFactoryInstance.get(); - } - - @Override - protected Executor getExecutor() { - return executor; - } -} diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java deleted file mode 100644 index 1a5a7a078..000000000 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcTransportMetadata.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.a2a.server.grpc.quarkus; - -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; - -public class QuarkusGrpcTransportMetadata implements TransportMetadata { - @Override - public String getTransportProtocol() { - return TransportProtocol.GRPC.asString(); - } -} diff --git a/reference/grpc/src/main/resources/META-INF/beans.xml b/reference/grpc/src/main/resources/META-INF/beans.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/reference/grpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata b/reference/grpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index 3eb991c3c..000000000 --- a/reference/grpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1 +0,0 @@ -io.a2a.server.grpc.quarkus.QuarkusGrpcTransportMetadata \ No newline at end of file diff --git a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java b/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java deleted file mode 100644 index fc57c705d..000000000 --- a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java +++ /dev/null @@ -1,176 +0,0 @@ -package io.a2a.server.grpc.quarkus; - -import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; - -import java.util.concurrent.atomic.AtomicInteger; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.apps.common.TestUtilsBean; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.transport.grpc.handler.GrpcHandler; - -@Path("/test") -@ApplicationScoped -public class A2ATestResource { - @Inject - TestUtilsBean testUtilsBean; - - private final AtomicInteger streamingSubscribedCount = new AtomicInteger(0); - - @PostConstruct - public void init() { - GrpcHandler.setStreamingSubscribedRunnable(streamingSubscribedCount::incrementAndGet); - } - - - @POST - @Path("/task") - @Consumes(MediaType.APPLICATION_JSON) - public Response saveTask(String body) throws Exception { - Task task = JsonUtil.fromJson(body, Task.class); - testUtilsBean.saveTask(task); - return Response.ok().build(); - } - - @GET - @Path("/task/{taskId}") - public Response getTask(@PathParam("taskId") String taskId) throws Exception { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - return Response.status(404).build(); - } - return Response.ok() - .entity(JsonUtil.toJson(task)) - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) - .build(); - } - - @DELETE - @Path("/task/{taskId}") - public Response deleteTask(@PathParam("taskId") String taskId) { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - return Response.status(404).build(); - } - testUtilsBean.deleteTask(taskId); - return Response.ok() - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) - .build(); - } - - @POST - @Path("/queue/ensure/{taskId}") - public Response ensureQueue(@PathParam("taskId") String taskId) { - testUtilsBean.ensureQueue(taskId); - return Response.ok().build(); - } - - @POST - @Path("/queue/enqueueTaskStatusUpdateEvent/{taskId}") - public Response enqueueTaskStatusUpdateEvent(@PathParam("taskId") String taskId, String body) throws Exception { - TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - return Response.ok().build(); - } - - @POST - @Path("/queue/enqueueTaskArtifactUpdateEvent/{taskId}") - public Response enqueueTaskArtifactUpdateEvent(@PathParam("taskId") String taskId, String body) throws Exception { - TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - return Response.ok().build(); - } - - @GET - @Path("/streamingSubscribedCount") - @Produces(TEXT_PLAIN) - public Response getStreamingSubscribedCount() { - return Response.ok(String.valueOf(streamingSubscribedCount.get()), TEXT_PLAIN).build(); - } - - @GET - @Path("/queue/childCount/{taskId}") - @Produces(TEXT_PLAIN) - public Response getChildQueueCount(@PathParam("taskId") String taskId) { - int count = testUtilsBean.getChildQueueCount(taskId); - return Response.ok(String.valueOf(count), TEXT_PLAIN).build(); - } - - @DELETE - @Path("/task/{taskId}/config/{configId}") - public Response deleteTaskPushNotificationConfig(@PathParam("taskId") String taskId, @PathParam("configId") String configId) { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - return Response.status(404).build(); - } - testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); - return Response.ok() - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) - .build(); - } - - @POST - @Path("/task/{taskId}") - @Consumes(MediaType.APPLICATION_JSON) - public Response savePushNotificationConfigInStore(@PathParam("taskId") String taskId, String body) throws Exception { - PushNotificationConfig notificationConfig = JsonUtil.fromJson(body, PushNotificationConfig.class); - if (notificationConfig == null) { - return Response.status(404).build(); - } - testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); - return Response.ok().build(); - } - - /** - * REST endpoint to wait for queue poller to start. - * Waits for the EventConsumer polling loop to start for the specified task's queue, - * ensuring the queue is ready to receive and process events. - * - * @param taskId the task ID whose queue poller to wait for - * @return HTTP 200 response when poller has started - * @throws InterruptedException if interrupted while waiting - */ - @POST - @Path("/queue/awaitPollerStart/{taskId}") - public Response awaitQueuePollerStart(@PathParam("taskId") String taskId) throws InterruptedException { - testUtilsBean.awaitQueuePollerStart(taskId); - return Response.ok().build(); - } - - /** - * REST endpoint to wait for child queue count to stabilize. - * Waits for the specified task's child queue count to match expectedCount for 3 consecutive - * checks (150ms total), ensuring EventConsumer polling loops have started. - * - * @param taskId the task ID whose child queues to monitor - * @param expectedCount the expected number of active child queues - * @param timeoutMs maximum time to wait in milliseconds - * @return HTTP 200 response with "true" if count stabilized, "false" if timeout occurred - * @throws InterruptedException if interrupted while waiting - */ - @POST - @Path("/queue/awaitChildCountStable/{taskId}/{expectedCount}/{timeoutMs}") - public Response awaitChildQueueCountStable(@PathParam("taskId") String taskId, - @PathParam("expectedCount") int expectedCount, - @PathParam("timeoutMs") long timeoutMs) throws InterruptedException { - boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); - return Response.ok(String.valueOf(stable), TEXT_PLAIN).build(); - } -} diff --git a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java b/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java deleted file mode 100644 index 24320b94d..000000000 --- a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package io.a2a.server.grpc.quarkus; - -import java.util.concurrent.TimeUnit; - -import io.a2a.client.ClientBuilder; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.server.apps.common.AbstractA2AServerTest; -import io.a2a.spec.TransportProtocol; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.AfterAll; - -@QuarkusTest -public class QuarkusA2AGrpcTest extends AbstractA2AServerTest { - - private static ManagedChannel channel; - - public QuarkusA2AGrpcTest() { - super(8081); // HTTP server port for utility endpoints - } - - @Override - protected String getTransportProtocol() { - return TransportProtocol.GRPC.asString(); - } - - @Override - protected String getTransportUrl() { - // gRPC server runs on port 8081, which is the same port as the main web server. - // This is from the setting on the - return "localhost:8081"; - } - - @Override - protected void configureTransport(ClientBuilder builder) { - builder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(target -> { - channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build(); - return channel; - })); - } - - @AfterAll - public static void closeChannel() { - channel.shutdownNow(); - try { - channel.awaitTermination(10, TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } -} \ No newline at end of file diff --git a/reference/grpc/src/test/resources/a2a-requesthandler-test.properties b/reference/grpc/src/test/resources/a2a-requesthandler-test.properties deleted file mode 100644 index a8f637a17..000000000 --- a/reference/grpc/src/test/resources/a2a-requesthandler-test.properties +++ /dev/null @@ -1 +0,0 @@ -preferred-transport=GRPC diff --git a/reference/grpc/src/test/resources/application.properties b/reference/grpc/src/test/resources/application.properties deleted file mode 100644 index e9a00d696..000000000 --- a/reference/grpc/src/test/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -# Use the new gRPC implementation which uses the main HTTP port -quarkus.grpc.server.use-separate-server=false -quarkus.http.port=8081 \ No newline at end of file diff --git a/reference/jsonrpc/README.md b/reference/jsonrpc/README.md deleted file mode 100644 index 2a7f0f902..000000000 --- a/reference/jsonrpc/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# A2A Java SDK Reference Server Integration - -This is a reference server for the A2A SDK for Java, that we use to run tests, as well as to demonstrate examples. - -It is based on [Quarkus](https://quarkus.io), and makes use of Quarkus's [Reactive Routes](https://quarkus.io/guides/reactive-routes). - -It is a great choice if you use Quarkus! \ No newline at end of file diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml deleted file mode 100644 index 8f4c5fb87..000000000 --- a/reference/jsonrpc/pom.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-reference-jsonrpc - - jar - - Java A2A Reference Server: JSONRPC - Java SDK for the Agent2Agent Protocol (A2A) - A2A JSONRPC Reference Server (based on Quarkus) - - - - ${project.groupId} - a2a-java-sdk-reference-common - - - ${project.groupId} - a2a-java-sdk-transport-jsonrpc - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-http-client-vertx - test - - - ${project.groupId} - a2a-java-sdk-tests-server-common - provided - - - ${project.groupId} - a2a-java-sdk-tests-server-common - test-jar - test - - - - ${project.groupId} - a2a-java-sdk-client-transport-jsonrpc - test - - - io.quarkus - quarkus-reactive-routes - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - org.slf4j - slf4j-api - - - io.quarkus - quarkus-junit5 - test - - - io.quarkus - quarkus-rest-client - test - - - org.junit.jupiter - junit-jupiter-api - test - - - io.rest-assured - rest-assured - test - - - org.mockito - mockito-core - test - - - org.mockito - mockito-junit-jupiter - test - - - diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java deleted file mode 100644 index 971a0cc77..000000000 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java +++ /dev/null @@ -1,413 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.HEADERS_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; -import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; -import static jakarta.ws.rs.core.MediaType.SERVER_SENT_EVENTS; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicLong; - -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - -import com.google.gson.JsonSyntaxException; -import io.a2a.common.A2AHeaders; -import io.a2a.server.util.sse.SseFormatter; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.jsonrpc.common.json.IdJsonMappingException; -import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; -import io.a2a.jsonrpc.common.json.JsonMappingException; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.jsonrpc.common.json.MethodNotFoundJsonMappingException; -import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; -import io.a2a.jsonrpc.common.wrappers.A2ARequest; -import io.a2a.jsonrpc.common.wrappers.A2AResponse; -import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; -import io.a2a.jsonrpc.common.wrappers.NonStreamingJSONRPCRequest; -import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.auth.User; -import io.a2a.server.extensions.A2AExtensions; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.A2AError; -import io.a2a.spec.InternalError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.transport.jsonrpc.handler.JSONRPCHandler; -import io.quarkus.security.Authenticated; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Route; -import io.smallrye.mutiny.Multi; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RoutingContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class A2AServerRoutes { - - @Inject - JSONRPCHandler jsonRpcHandler; - - // Hook so testing can wait until the MultiSseSupport is subscribed. - // Without this we get intermittent failures - private static volatile Runnable streamingMultiSseSupportSubscribedRunnable; - - @Inject - @Internal - Executor executor; - - @Inject - Instance callContextFactory; - - @Route(path = "/", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - @Authenticated - public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { - boolean streaming = false; - ServerCallContext context = createCallContext(rc); - A2AResponse nonStreamingResponse = null; - Multi> streamingResponse = null; - A2AErrorResponse error = null; - try { - A2ARequest request = JSONRPCUtils.parseRequestBody(body, extractTenant(rc)); - context.getState().put(METHOD_NAME_KEY, request.getMethod()); - if (request instanceof NonStreamingJSONRPCRequest nonStreamingRequest) { - nonStreamingResponse = processNonStreamingRequest(nonStreamingRequest, context); - } else { - streaming = true; - streamingResponse = processStreamingRequest(request, context); - } - } catch (A2AError e) { - error = new A2AErrorResponse(e); - } catch (InvalidParamsJsonMappingException e) { - error = new A2AErrorResponse(e.getId(), new io.a2a.spec.InvalidParamsError(null, e.getMessage(), null)); - } catch (MethodNotFoundJsonMappingException e) { - error = new A2AErrorResponse(e.getId(), new io.a2a.spec.MethodNotFoundError(null, e.getMessage(), null)); - } catch (IdJsonMappingException e) { - error = new A2AErrorResponse(e.getId(), new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); - } catch (JsonMappingException e) { - // General JsonMappingException - treat as InvalidRequest - error = new A2AErrorResponse(new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); - } catch (JsonSyntaxException e) { - error = new A2AErrorResponse(new JSONParseError(e.getMessage())); - } catch (JsonProcessingException e) { - error = new A2AErrorResponse(new JSONParseError(e.getMessage())); - } catch (Throwable t) { - error = new A2AErrorResponse(new InternalError(t.getMessage())); - } finally { - if (error != null) { - rc.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) - .end(serializeResponse(error)); - } else if (streaming) { - final Multi> finalStreamingResponse = streamingResponse; - executor.execute(() -> { - // Convert Multi to Multi with SSE formatting - AtomicLong eventIdCounter = new AtomicLong(0); - Multi sseEvents = finalStreamingResponse - .map(response -> SseFormatter.formatResponseAsSSE(response, eventIdCounter.getAndIncrement())); - // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); - }); - - } else { - rc.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) - .end(serializeResponse(nonStreamingResponse)); - } - } - } - - /** - * /** - * Handles incoming GET requests to the agent card endpoint. - * Returns the agent card in JSON format. - * - * @return the agent card - */ - @Route(path = "/.well-known/agent-card.json", methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) - public String getAgentCard() throws JsonProcessingException { - return JsonUtil.toJson(jsonRpcHandler.getAgentCard()); - } - - private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest request, ServerCallContext context) { - if (request instanceof GetTaskRequest req) { - return jsonRpcHandler.onGetTask(req, context); - } - if (request instanceof CancelTaskRequest req) { - return jsonRpcHandler.onCancelTask(req, context); - } - if (request instanceof ListTasksRequest req) { - return jsonRpcHandler.onListTasks(req, context); - } - if (request instanceof CreateTaskPushNotificationConfigRequest req) { - return jsonRpcHandler.setPushNotificationConfig(req, context); - } - if (request instanceof GetTaskPushNotificationConfigRequest req) { - return jsonRpcHandler.getPushNotificationConfig(req, context); - } - if (request instanceof SendMessageRequest req) { - return jsonRpcHandler.onMessageSend(req, context); - } - if (request instanceof ListTaskPushNotificationConfigRequest req) { - return jsonRpcHandler.listPushNotificationConfig(req, context); - } - if (request instanceof DeleteTaskPushNotificationConfigRequest req) { - return jsonRpcHandler.deletePushNotificationConfig(req, context); - } - if (request instanceof GetExtendedAgentCardRequest req) { - return jsonRpcHandler.onGetExtendedCardRequest(req, context); - } - return generateErrorResponse(request, new UnsupportedOperationError()); - } - - private Multi> processStreamingRequest( - A2ARequest request, ServerCallContext context) { - Flow.Publisher> publisher; - if (request instanceof SendStreamingMessageRequest req) { - publisher = jsonRpcHandler.onMessageSendStream(req, context); - } else if (request instanceof SubscribeToTaskRequest req) { - publisher = jsonRpcHandler.onSubscribeToTask(req, context); - } else { - return Multi.createFrom().item(generateErrorResponse(request, new UnsupportedOperationError())); - } - return Multi.createFrom().publisher(publisher); - } - - private A2AResponse generateErrorResponse(A2ARequest request, A2AError error) { - return new A2AErrorResponse(request.getId(), error); - } - - static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { - streamingMultiSseSupportSubscribedRunnable = runnable; - } - - private ServerCallContext createCallContext(RoutingContext rc) { - if (callContextFactory.isUnsatisfied()) { - User user; - if (rc.user() == null) { - user = UnauthenticatedUser.INSTANCE; - } else { - user = new User() { - @Override - public boolean isAuthenticated() { - return rc.userContext().authenticated(); - } - - @Override - public String getUsername() { - return rc.user().subject(); - } - }; - } - Map state = new HashMap<>(); - // TODO Python's impl has - // state['auth'] = request.auth - // in jsonrpc_app.py. Figure out what this maps to in what Vert.X gives us - - Map headers = new HashMap<>(); - Set headerNames = rc.request().headers().names(); - headerNames.forEach(name -> headers.put(name, rc.request().getHeader(name))); - state.put(HEADERS_KEY, headers); - state.put(TENANT_KEY, extractTenant(rc)); - state.put(TRANSPORT_KEY, TransportProtocol.JSONRPC); - - // Extract requested protocol version from X-A2A-Version header - String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); - - // Extract requested extensions from X-A2A-Extensions header - List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders.X_A2A_EXTENSIONS); - Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); - - return new ServerCallContext(user, state, requestedExtensions, requestedVersion); - } else { - CallContextFactory builder = callContextFactory.get(); - return builder.build(rc); - } - } - - private String extractTenant(RoutingContext rc) { - String tenantPath = rc.normalizedPath(); - if (tenantPath == null || tenantPath.isBlank()) { - return ""; - } - if (tenantPath.startsWith("/")) { - tenantPath = tenantPath.substring(1); - } - if(tenantPath.endsWith("/")) { - tenantPath = tenantPath.substring(0, tenantPath.length() -1); - } - return tenantPath; - } - - private static String serializeResponse(A2AResponse response) { - // For error responses, use Jackson serialization (errors are standardized) - if (response instanceof A2AErrorResponse error) { - return JSONRPCUtils.toJsonRPCErrorResponse(error.getId(), error.getError()); - } - if (response.getError() != null) { - return JSONRPCUtils.toJsonRPCErrorResponse(response.getId(), response.getError()); - } - // Convert domain response to protobuf message and serialize - com.google.protobuf.MessageOrBuilder protoMessage = convertToProto(response); - return JSONRPCUtils.toJsonRPCResultResponse(response.getId(), protoMessage); - } - - private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse response) { - if (response instanceof GetTaskResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); - } else if (response instanceof CancelTaskResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); - } else if (response instanceof SendMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessage(r.getResult()); - } else if (response instanceof ListTasksResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTasksResult(r.getResult()); - } else if (response instanceof CreateTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.createTaskPushNotificationConfigResponse(r.getResult()); - } else if (response instanceof GetTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getTaskPushNotificationConfigResponse(r.getResult()); - } else if (response instanceof ListTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTaskPushNotificationConfigResponse(r.getResult()); - } else if (response instanceof DeleteTaskPushNotificationConfigResponse) { - // DeleteTaskPushNotificationConfig has no result body, just return empty message - return com.google.protobuf.Empty.getDefaultInstance(); - } else if (response instanceof GetExtendedAgentCardResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getExtendedCardResponse(r.getResult()); - } else if (response instanceof SendStreamingMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessageStream(r.getResult()); - } else { - throw new IllegalArgumentException("Unknown response type: " + response.getClass().getName()); - } - } - - /** - * Simplified SSE support for Vert.x/Quarkus. - *

- * This class only handles HTTP-specific concerns (writing to response, backpressure, disconnect). - * SSE formatting and JSON serialization are handled by {@link SseFormatter}. - */ - private static class MultiSseSupport { - private static final Logger logger = LoggerFactory.getLogger(MultiSseSupport.class); - - private MultiSseSupport() { - // Avoid direct instantiation. - } - - /** - * Write SSE-formatted strings to HTTP response. - * - * @param sseStrings Multi stream of SSE-formatted strings (from SseFormatter) - * @param rc Vert.x routing context - * @param context A2A server call context (for EventConsumer cancellation) - */ - public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { - HttpServerResponse response = rc.response(); - - sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { - Flow.Subscription upstream; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.upstream = subscription; - this.upstream.request(1); - - // Detect client disconnect and call EventConsumer.cancel() directly - response.closeHandler(v -> { - logger.info("SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); - context.invokeEventConsumerCancelCallback(); - subscription.cancel(); - }); - - // Notify tests that we are subscribed - Runnable runnable = streamingMultiSseSupportSubscribedRunnable; - if (runnable != null) { - runnable.run(); - } - } - - @Override - public void onNext(String sseEvent) { - // Set SSE headers on first event - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - response.setChunked(true); - } - - // Write SSE-formatted string to response - response.write(Buffer.buffer(sseEvent), new Handler>() { - @Override - public void handle(AsyncResult ar) { - if (ar.failed()) { - // Client disconnected or write failed - cancel upstream to stop EventConsumer - upstream.cancel(); - rc.fail(ar.cause()); - } else { - upstream.request(1); - } - } - }); - } - - @Override - public void onError(Throwable throwable) { - // Cancel upstream to stop EventConsumer when error occurs - upstream.cancel(); - rc.fail(throwable); - } - - @Override - public void onComplete() { - if (response.bytesWritten() == 0) { - // No events written - still set SSE content type - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); - } - }); - } - } -} diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java deleted file mode 100644 index d40bc65f0..000000000 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/CallContextFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import io.a2a.server.ServerCallContext; -import io.vertx.ext.web.RoutingContext; - -public interface CallContextFactory { - ServerCallContext build(RoutingContext rc); -} diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java deleted file mode 100644 index 5cff0d7f7..000000000 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/QuarkusJSONRPCTransportMetadata.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; - -public class QuarkusJSONRPCTransportMetadata implements TransportMetadata { - - @Override - public String getTransportProtocol() { - return TransportProtocol.JSONRPC.asString(); - } -} diff --git a/reference/jsonrpc/src/main/resources/META-INF/beans.xml b/reference/jsonrpc/src/main/resources/META-INF/beans.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/reference/jsonrpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata b/reference/jsonrpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index d9a5494b4..000000000 --- a/reference/jsonrpc/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1 +0,0 @@ -io.a2a.server.apps.quarkus.QuarkusJSONRPCTransportMetadata \ No newline at end of file diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java deleted file mode 100644 index 9d600f53d..000000000 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java +++ /dev/null @@ -1,732 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; -import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.TENANT_KEY; -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.Collections; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; - -import jakarta.enterprise.inject.Instance; - -import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; -import io.a2a.server.ServerCallContext; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.transport.jsonrpc.handler.JSONRPCHandler; -import io.vertx.core.MultiMap; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RequestBody; -import io.vertx.ext.web.RoutingContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; - -/** - * Unit test for JSON-RPC A2AServerRoutes that verifies the method names are properly set - * in the ServerCallContext for all request types. - */ -public class A2AServerRoutesTest { - - private A2AServerRoutes routes; - private JSONRPCHandler mockJsonRpcHandler; - private Executor mockExecutor; - private Instance mockCallContextFactory; - private RoutingContext mockRoutingContext; - private HttpServerRequest mockRequest; - private HttpServerResponse mockHttpResponse; - private MultiMap mockHeaders; - private RequestBody mockRequestBody; - - @BeforeEach - public void setUp() { - routes = new A2AServerRoutes(); - mockJsonRpcHandler = mock(JSONRPCHandler.class); - mockExecutor = mock(Executor.class); - mockCallContextFactory = mock(Instance.class); - mockRoutingContext = mock(RoutingContext.class); - mockRequest = mock(HttpServerRequest.class); - mockHttpResponse = mock(HttpServerResponse.class); - mockHeaders = MultiMap.caseInsensitiveMultiMap(); - mockRequestBody = mock(RequestBody.class); - - // Inject mocks via reflection since we can't use @InjectMocks - setField(routes, "jsonRpcHandler", mockJsonRpcHandler); - setField(routes, "executor", mockExecutor); - setField(routes, "callContextFactory", mockCallContextFactory); - - // Setup common mock behavior - when(mockCallContextFactory.isUnsatisfied()).thenReturn(true); - when(mockRoutingContext.request()).thenReturn(mockRequest); - when(mockRoutingContext.response()).thenReturn(mockHttpResponse); - when(mockRoutingContext.user()).thenReturn(null); - when(mockRequest.headers()).thenReturn(mockHeaders); - when(mockRoutingContext.body()).thenReturn(mockRequestBody); - when(mockRoutingContext.normalizedPath()).thenReturn("/"); - - // Chain the response methods properly - when(mockHttpResponse.setStatusCode(any(Integer.class))).thenReturn(mockHttpResponse); - when(mockHttpResponse.putHeader(any(CharSequence.class), any(CharSequence.class))).thenReturn(mockHttpResponse); - when(mockHttpResponse.end(anyString())).thenReturn(null); - when(mockHttpResponse.setChunked(any(Boolean.class))).thenReturn(mockHttpResponse); - when(mockHttpResponse.headers()).thenReturn(mockHeaders); - } - - @Test - public void testSendMessage_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "SendMessage", - "params": { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me a joke" - } - ], - "metadata": {} - }, - "configuration": { - "acceptedOutputModes": ["text"], - "blocking": true - }, - "metadata": {} - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with a Task - Task responseTask = Task.builder() - .id("task-123") - .contextId("context-1234") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - SendMessageResponse realResponse = new SendMessageResponse("1", responseTask); - when(mockJsonRpcHandler.onMessageSend(any(SendMessageRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onMessageSend(any(SendMessageRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SEND_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testSendStreamingMessage_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "SendStreamingMessage", - "params": { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me a joke" - } - ], - "metadata": {} - }, - "configuration": { - "acceptedOutputModes": ["text"], - "blocking": true - }, - "metadata": {} - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - @SuppressWarnings("unchecked") - Flow.Publisher mockPublisher = mock(Flow.Publisher.class); - when(mockJsonRpcHandler.onMessageSendStream(any(SendStreamingMessageRequest.class), - any(ServerCallContext.class))).thenReturn(mockPublisher); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onMessageSendStream(any(SendStreamingMessageRequest.class), - contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SEND_STREAMING_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testGetTask_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "GetTask", - "params": { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "historyLength": 10 - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with a Task - Task responseTask = Task.builder() - .id("de38c76d-d54c-436c-8b9f-4c2703648d64") - .contextId("context-1234") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); - when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(GET_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testCancelTask_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "CancelTask", - "params": { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64" - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with a Task - Task responseTask = Task.builder() - .id("de38c76d-d54c-436c-8b9f-4c2703648d64") - .contextId("context-1234") - .status(new TaskStatus(TaskState.TASK_STATE_CANCELED)) - .build(); - CancelTaskResponse realResponse = new CancelTaskResponse("1", responseTask); - when(mockJsonRpcHandler.onCancelTask(any(CancelTaskRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onCancelTask(any(CancelTaskRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testTaskResubscription_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "SubscribeToTask", - "params": { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64" - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - @SuppressWarnings("unchecked") - Flow.Publisher mockPublisher = mock(Flow.Publisher.class); - when(mockJsonRpcHandler.onSubscribeToTask(any(SubscribeToTaskRequest.class), - any(ServerCallContext.class))).thenReturn(mockPublisher); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onSubscribeToTask(any(SubscribeToTaskRequest.class), - contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SUBSCRIBE_TO_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testCreateTaskPushNotificationConfig_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "CreateTaskPushNotificationConfig", - "params": { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "configId": "config-123", - "config": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with a TaskPushNotificationConfig - TaskPushNotificationConfig responseConfig = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("config-123") - .url("https://example.com/callback") - .authentication(new AuthenticationInfo("jwt", null)) - .build(), - "tenant"); - - CreateTaskPushNotificationConfigResponse realResponse = new CreateTaskPushNotificationConfigResponse("1", responseConfig); - when(mockJsonRpcHandler.setPushNotificationConfig(any(CreateTaskPushNotificationConfigRequest.class), - any(ServerCallContext.class))).thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).setPushNotificationConfig(any(CreateTaskPushNotificationConfigRequest.class), - contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testGetTaskPushNotificationConfig_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "GetTaskPushNotificationConfig", - "params": { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "config-456" - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with a TaskPushNotificationConfig - TaskPushNotificationConfig responseConfig = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("config-456") - .url("https://example.com/callback") - .build(), - null - ); - GetTaskPushNotificationConfigResponse realResponse = new GetTaskPushNotificationConfigResponse("1", responseConfig); - when(mockJsonRpcHandler.getPushNotificationConfig(any(GetTaskPushNotificationConfigRequest.class), - any(ServerCallContext.class))).thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).getPushNotificationConfig(any(GetTaskPushNotificationConfigRequest.class), - contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testListTaskPushNotificationConfig_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "ListTaskPushNotificationConfig", - "params": { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "pageSize": 0, - "pageToken": "" - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with a list of TaskPushNotificationConfig - TaskPushNotificationConfig config = new TaskPushNotificationConfig( - "de38c76d-d54c-436c-8b9f-4c2703648d64", - PushNotificationConfig.builder() - .id("config-123") - .url("https://example.com/callback") - .build(), - null - ); - ListTaskPushNotificationConfigResponse realResponse = new ListTaskPushNotificationConfigResponse("1", new ListTaskPushNotificationConfigResult(singletonList(config))); - when(mockJsonRpcHandler.listPushNotificationConfig(any(ListTaskPushNotificationConfigRequest.class), - any(ServerCallContext.class))).thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).listPushNotificationConfig(any(ListTaskPushNotificationConfigRequest.class), - contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testDeleteTaskPushNotificationConfig_MethodNameSetInContext() { - // Arrange - using protobuf JSON format - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "DeleteTaskPushNotificationConfig", - "params": { - "taskId": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "id": "config-456" - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with id - DeleteTaskPushNotificationConfigResponse realResponse = new DeleteTaskPushNotificationConfigResponse("1"); - when(mockJsonRpcHandler.deletePushNotificationConfig(any(DeleteTaskPushNotificationConfigRequest.class), - any(ServerCallContext.class))).thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).deletePushNotificationConfig(any(DeleteTaskPushNotificationConfigRequest.class), - contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testGetExtendedCard_MethodNameSetInContext() { - // Arrange - String jsonRpcRequest = "{\"jsonrpc\":\"2.0\",\"id\":\"5\",\"method\":\"" + GET_EXTENDED_AGENT_CARD_METHOD - + "\",\"id\":1}"; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - // Create a real response with an AgentCard - AgentCard agentCard = AgentCard.builder() - .name("Test Agent") - .description("Test agent description") - .version("1.0.0") - .capabilities(AgentCapabilities.builder().build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.emptyList()) - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999"))) - .build(); - GetExtendedAgentCardResponse realResponse = new GetExtendedAgentCardResponse(1, agentCard); - when(mockJsonRpcHandler.onGetExtendedCardRequest( - any(GetExtendedAgentCardRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onGetExtendedCardRequest( - any(GetExtendedAgentCardRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(GET_EXTENDED_AGENT_CARD_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testTenantExtraction_MultiSegmentPath() { - // Arrange - simulate request to /test/titi - when(mockRoutingContext.normalizedPath()).thenReturn("/test/titi"); - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "GetTask", - "params": { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "historyLength": 10 - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - Task responseTask = Task.builder() - .id("de38c76d-d54c-436c-8b9f-4c2703648d64") - .contextId("context-1234") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); - when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals("test/titi", capturedContext.getState().get(TENANT_KEY)); - } - - @Test - public void testTenantExtraction_RootPath() { - // Arrange - simulate request to / - when(mockRoutingContext.normalizedPath()).thenReturn("/"); - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "GetTask", - "params": { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "historyLength": 10 - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - Task responseTask = Task.builder() - .id("de38c76d-d54c-436c-8b9f-4c2703648d64") - .contextId("context-1234") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); - when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals("", capturedContext.getState().get(TENANT_KEY)); - } - - @Test - public void testTenantExtraction_SingleSegmentPath() { - // Arrange - simulate request to /tenant1 - when(mockRoutingContext.normalizedPath()).thenReturn("/tenant1"); - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "GetTask", - "params": { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "historyLength": 10 - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - Task responseTask = Task.builder() - .id("de38c76d-d54c-436c-8b9f-4c2703648d64") - .contextId("context-1234") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); - when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals("tenant1", capturedContext.getState().get(TENANT_KEY)); - } - - @Test - public void testTenantExtraction_ThreeSegmentPath() { - // Arrange - simulate request to /tenant1/api/v1 - when(mockRoutingContext.normalizedPath()).thenReturn("/tenant1/api/v1"); - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "GetTask", - "params": { - "id": "de38c76d-d54c-436c-8b9f-4c2703648d64", - "historyLength": 10 - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - Task responseTask = Task.builder() - .id("de38c76d-d54c-436c-8b9f-4c2703648d64") - .contextId("context-1234") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - GetTaskResponse realResponse = new GetTaskResponse("1", responseTask); - when(mockJsonRpcHandler.onGetTask(any(GetTaskRequest.class), any(ServerCallContext.class))) - .thenReturn(realResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals("tenant1/api/v1", capturedContext.getState().get(TENANT_KEY)); - } - - @Test - public void testTenantExtraction_StreamingRequest() { - // Arrange - simulate streaming request to /myTenant/api - when(mockRoutingContext.normalizedPath()).thenReturn("/myTenant/api"); - String jsonRpcRequest = """ - { - "jsonrpc": "2.0", - "id": "cd4c76de-d54c-436c-8b9f-4c2703648d64", - "method": "SendStreamingMessage", - "params": { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me a joke" - } - ], - "metadata": {} - }, - "configuration": { - "acceptedOutputModes": ["text"], - "blocking": true - }, - "metadata": {} - } - }"""; - when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); - - @SuppressWarnings("unchecked") - Flow.Publisher mockPublisher = mock(Flow.Publisher.class); - when(mockJsonRpcHandler.onMessageSendStream(any(SendStreamingMessageRequest.class), - any(ServerCallContext.class))).thenReturn(mockPublisher); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.invokeJSONRPCHandler(jsonRpcRequest, mockRoutingContext); - - // Assert - verify(mockJsonRpcHandler).onMessageSendStream(any(SendStreamingMessageRequest.class), - contextCaptor.capture()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals("myTenant/api", capturedContext.getState().get(TENANT_KEY)); - } - - /** - * Helper method to set a field via reflection for testing purposes. - */ - private void setField(Object target, String fieldName, Object value) { - try { - var field = target.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - field.set(target, value); - } catch (Exception e) { - throw new RuntimeException("Failed to set field: " + fieldName, e); - } - } -} diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java deleted file mode 100644 index 937c8a2b1..000000000 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java +++ /dev/null @@ -1,220 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; -import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; - -import java.util.concurrent.atomic.AtomicInteger; - -import jakarta.annotation.PostConstruct; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.apps.common.TestUtilsBean; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Param; -import io.quarkus.vertx.web.Route; -import io.vertx.ext.web.RoutingContext; - -/** - * Exposes the {@link TestUtilsBean} via REST using Quarkus Reactive Routes - */ -@Singleton -public class A2ATestRoutes { - @Inject - TestUtilsBean testUtilsBean; - - @Inject - A2AServerRoutes a2AServerRoutes; - - AtomicInteger streamingSubscribedCount = new AtomicInteger(0); - - @PostConstruct - public void init() { - A2AServerRoutes.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet()); - } - - - @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void saveTask(@Body String body, RoutingContext rc) { - try { - Task task = JsonUtil.fromJson(body, Task.class); - testUtilsBean.saveTask(task); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void getTask(@Param String taskId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - rc.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) - .end(JsonUtil.toJson(task)); - - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTask(@Param String taskId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - testUtilsBean.deleteTask(taskId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) - public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { - try { - testUtilsBean.ensureQueue(taskId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { - - try { - TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { - - try { - TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getStreamingSubscribedCount(RoutingContext rc) { - rc.response() - .setStatusCode(200) - .end(String.valueOf(streamingSubscribedCount.get())); - } - - @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getChildQueueCount(@Param String taskId, RoutingContext rc) { - int count = testUtilsBean.getChildQueueCount(taskId); - rc.response() - .setStatusCode(200) - .end(String.valueOf(count)); - } - - @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { - try { - PushNotificationConfig notificationConfig = JsonUtil.fromJson(body, PushNotificationConfig.class); - if (notificationConfig == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - /** - * REST endpoint to wait for child queue count to stabilize. - * Waits for the specified task's child queue count to match expectedCount for 3 consecutive - * checks (150ms total), ensuring EventConsumer polling loops have started. - * - * @param taskId the task ID whose child queues to monitor - * @param expectedCountStr the expected number of active child queues (as string) - * @param timeoutMsStr maximum time to wait in milliseconds (as string) - * @param rc the Vert.x routing context - */ - @Route(path = "/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void awaitChildQueueCountStable(@Param("taskId") String taskId, @Param("expectedCount") String expectedCountStr, @Param("timeoutMs") String timeoutMsStr, RoutingContext rc) { - try { - int expectedCount = Integer.parseInt(expectedCountStr); - long timeoutMs = Long.parseLong(timeoutMsStr); - boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); - rc.response() - .setStatusCode(200) - .end(String.valueOf(stable)); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - private void errorResponse(Throwable t, RoutingContext rc) { - t.printStackTrace(); - rc.response() - .setStatusCode(500) - .putHeader(CONTENT_TYPE, TEXT_PLAIN) - .end(); - } - -} diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java deleted file mode 100644 index 4f1e76251..000000000 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCJdkTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.JdkA2AHttpClient; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.quarkus.test.junit.QuarkusTest; - -@QuarkusTest -public class QuarkusA2AJSONRPCJdkTest extends QuarkusA2AJSONRPCTest { - - @Override - protected void configureTransport(ClientBuilder builder) { - builder.withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder().httpClient(new JdkA2AHttpClient())); - } -} diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCTest.java b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCTest.java deleted file mode 100644 index 4123262cb..000000000 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import io.a2a.client.ClientBuilder; -import io.a2a.server.apps.common.AbstractA2AServerTest; -import io.a2a.spec.TransportProtocol; - -public abstract class QuarkusA2AJSONRPCTest extends AbstractA2AServerTest { - - public QuarkusA2AJSONRPCTest() { - super(8081); - } - - @Override - protected String getTransportProtocol() { - return TransportProtocol.JSONRPC.asString(); - } - - @Override - protected String getTransportUrl() { - return "http://localhost:8081"; - } - - @Override - protected abstract void configureTransport(ClientBuilder builder); -} diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java deleted file mode 100644 index 69370566b..000000000 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/QuarkusA2AJSONRPCVertxTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.a2a.server.apps.quarkus; - -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.VertxA2AHttpClient; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.quarkus.test.junit.QuarkusTest; -import io.vertx.core.Vertx; -import jakarta.inject.Inject; - -@QuarkusTest -public class QuarkusA2AJSONRPCVertxTest extends QuarkusA2AJSONRPCTest { - - @Inject - Vertx vertx; - - @Override - protected void configureTransport(ClientBuilder builder) { - builder.withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder().httpClient(new VertxA2AHttpClient(vertx))); - } -} diff --git a/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties b/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties deleted file mode 100644 index 2d2582df3..000000000 --- a/reference/jsonrpc/src/test/resources/a2a-requesthandler-test.properties +++ /dev/null @@ -1 +0,0 @@ -preferred-transport=JSONRPC diff --git a/reference/jsonrpc/src/test/resources/application.properties b/reference/jsonrpc/src/test/resources/application.properties deleted file mode 100644 index e612925d4..000000000 --- a/reference/jsonrpc/src/test/resources/application.properties +++ /dev/null @@ -1,6 +0,0 @@ -quarkus.arc.selected-alternatives=io.a2a.server.apps.common.TestHttpClient - -# Debug logging for event processing and request handling -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG diff --git a/reference/rest/README.md b/reference/rest/README.md deleted file mode 100644 index 2a7f0f902..000000000 --- a/reference/rest/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# A2A Java SDK Reference Server Integration - -This is a reference server for the A2A SDK for Java, that we use to run tests, as well as to demonstrate examples. - -It is based on [Quarkus](https://quarkus.io), and makes use of Quarkus's [Reactive Routes](https://quarkus.io/guides/reactive-routes). - -It is a great choice if you use Quarkus! \ No newline at end of file diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml deleted file mode 100644 index 412a11239..000000000 --- a/reference/rest/pom.xml +++ /dev/null @@ -1,126 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-reference-rest - - jar - - Java A2A Reference Server: JSON+HTTP/REST - Java SDK for the Agent2Agent Protocol (A2A) - A2A JSON+HTTP/REST Reference Server (based on Quarkus) - - - - ${project.groupId} - a2a-java-sdk-reference-common - - - ${project.groupId} - a2a-java-sdk-transport-rest - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-http-client-vertx - test - - - ${project.groupId} - a2a-java-sdk-client-transport-rest - test - - - ${project.groupId} - a2a-java-sdk-tests-server-common - provided - - - ${project.groupId} - a2a-java-sdk-tests-server-common - test-jar - test - - - com.google.protobuf - protobuf-java-util - test - - - io.quarkus - quarkus-reactive-routes - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - org.slf4j - slf4j-api - - - io.quarkus - quarkus-junit5 - test - - - io.quarkus - quarkus-rest-client - test - - - org.junit.jupiter - junit-jupiter-api - test - - - io.rest-assured - rest-assured - test - - - org.mockito - mockito-core - test - - - org.mockito - mockito-junit-jupiter - test - - - - - - maven-surefire-plugin - 3.5.4 - - - org.jboss.logmanager.LogManager - INFO - ${maven.home} - - - - - - diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java deleted file mode 100644 index 9b6bf510a..000000000 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java +++ /dev/null @@ -1,558 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; -import static io.a2a.transport.rest.context.RestContextKeys.HEADERS_KEY; -import static io.a2a.transport.rest.context.RestContextKeys.METHOD_NAME_KEY; -import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; -import static jakarta.ws.rs.core.MediaType.SERVER_SENT_EVENTS; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicLong; - -import io.a2a.server.util.sse.SseFormatter; - -import jakarta.annotation.security.PermitAll; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - -import io.a2a.common.A2AHeaders; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.auth.User; -import io.a2a.server.extensions.A2AExtensions; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.A2AError; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.TransportProtocol; -import io.a2a.transport.rest.handler.RestHandler; -import io.a2a.transport.rest.handler.RestHandler.HTTPRestResponse; -import io.a2a.transport.rest.handler.RestHandler.HTTPRestStreamingResponse; -import io.a2a.util.Utils; -import io.quarkus.security.Authenticated; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Route; -import io.smallrye.mutiny.Multi; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RoutingContext; -import org.jspecify.annotations.Nullable; - -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; - -import static io.a2a.transport.rest.context.RestContextKeys.TENANT_KEY; - -@Singleton -@Authenticated -public class A2AServerRoutes { - - private static final String HISTORY_LENGTH_PARAM = "historyLength"; - private static final String PAGE_SIZE_PARAM = "pageSize"; - private static final String PAGE_TOKEN_PARAM = "pageToken"; - private static final String STATUS_TIMESTAMP_AFTER = "statusTimestampAfter"; - - @Inject - RestHandler jsonRestHandler; - - // Hook so testing can wait until the MultiSseSupport is subscribed. - // Without this we get intermittent failures - private static volatile @Nullable - Runnable streamingMultiSseSupportSubscribedRunnable; - - @Inject - @Internal - Executor executor; - - @Inject - Instance callContextFactory; - - @Route(regex = "^\\/(?[^\\/]*\\/?)message:send$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void sendMessage(@Body String body, RoutingContext rc) { - ServerCallContext context = createCallContext(rc, SEND_MESSAGE_METHOD); - HTTPRestResponse response = null; - try { - response = jsonRestHandler.sendMessage(context, extractTenant(rc), body); - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)message:stream$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void sendMessageStreaming(@Body String body, RoutingContext rc) { - ServerCallContext context = createCallContext(rc, SEND_STREAMING_MESSAGE_METHOD); - HTTPRestStreamingResponse streamingResponse = null; - HTTPRestResponse error = null; - try { - HTTPRestResponse response = jsonRestHandler.sendStreamingMessage(context, extractTenant(rc), body); - if (response instanceof HTTPRestStreamingResponse hTTPRestStreamingResponse) { - streamingResponse = hTTPRestStreamingResponse; - } else { - error = response; - } - } finally { - if (error != null) { - sendResponse(rc, error); - } else if (streamingResponse != null) { - final HTTPRestStreamingResponse finalStreamingResponse = streamingResponse; - executor.execute(() -> { - // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) - AtomicLong eventIdCounter = new AtomicLong(0); - Multi sseEvents = Multi.createFrom().publisher(finalStreamingResponse.getPublisher()) - .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); - // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); - }); - } - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\??", order = 0, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) - public void listTasks(RoutingContext rc) { - ServerCallContext context = createCallContext(rc, LIST_TASK_METHOD); - HTTPRestResponse response = null; - try { - // Extract query parameters - String contextId = rc.request().params().get("contextId"); - String statusStr = rc.request().params().get("status"); - if (statusStr != null && !statusStr.isEmpty()) { - statusStr = statusStr.toUpperCase(); - } - String pageSizeStr = rc.request().params().get(PAGE_SIZE_PARAM); - String pageToken = rc.request().params().get(PAGE_TOKEN_PARAM); - String historyLengthStr = rc.request().params().get(HISTORY_LENGTH_PARAM); - String statusTimestampAfter = rc.request().params().get(STATUS_TIMESTAMP_AFTER); - String includeArtifactsStr = rc.request().params().get("includeArtifacts"); - - // Parse optional parameters - Integer pageSize = null; - if (pageSizeStr != null && !pageSizeStr.isEmpty()) { - pageSize = Integer.valueOf(pageSizeStr); - } - - Integer historyLength = null; - if (historyLengthStr != null && !historyLengthStr.isEmpty()) { - historyLength = Integer.valueOf(historyLengthStr); - } - - Boolean includeArtifacts = null; - if (includeArtifactsStr != null && !includeArtifactsStr.isEmpty()) { - includeArtifacts = Boolean.valueOf(includeArtifactsStr); - } - response = jsonRestHandler.listTasks(context, extractTenant(rc), contextId, statusStr, pageSize, pageToken, - historyLength, statusTimestampAfter, includeArtifacts); - } catch (NumberFormatException e) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("Invalid number format in parameters")); - } catch (IllegalArgumentException e) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("Invalid parameter value: " + e.getMessage())); - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^:^/]+)$", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) - public void getTask(RoutingContext rc) { - String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, GET_TASK_METHOD); - HTTPRestResponse response = null; - try { - if (taskId == null || taskId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else { - Integer historyLength = null; - if (rc.request().params().contains(HISTORY_LENGTH_PARAM)) { - historyLength = Integer.valueOf(rc.request().params().get(HISTORY_LENGTH_PARAM)); - } - response = jsonRestHandler.getTask(context, extractTenant(rc), taskId, historyLength); - } - } catch (NumberFormatException e) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad historyLength")); - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void cancelTask(RoutingContext rc) { - String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, CANCEL_TASK_METHOD); - HTTPRestResponse response = null; - try { - if (taskId == null || taskId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else { - response = jsonRestHandler.cancelTask(context, extractTenant(rc), taskId); - } - } catch (Throwable t) { - if (t instanceof A2AError error) { - response = jsonRestHandler.createErrorResponse(error); - } else { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } - } finally { - sendResponse(rc, response); - } - } - - private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response) { - if (response != null) { - rc.response() - .setStatusCode(response.getStatusCode()) - .putHeader(CONTENT_TYPE, response.getContentType()) - .end(response.getBody()); - } else { - rc.response().end(); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):subscribe$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void subscribeToTask(RoutingContext rc) { - String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, SUBSCRIBE_TO_TASK_METHOD); - HTTPRestStreamingResponse streamingResponse = null; - HTTPRestResponse error = null; - try { - if (taskId == null || taskId.isEmpty()) { - error = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else { - HTTPRestResponse response = jsonRestHandler.subscribeToTask(context, extractTenant(rc), taskId); - if (response instanceof HTTPRestStreamingResponse hTTPRestStreamingResponse) { - streamingResponse = hTTPRestStreamingResponse; - } else { - error = response; - } - } - } finally { - if (error != null) { - sendResponse(rc, error); - } else if (streamingResponse != null) { - final HTTPRestStreamingResponse finalStreamingResponse = streamingResponse; - executor.execute(() -> { - // Convert Flow.Publisher (JSON) to Multi (SSE-formatted) - AtomicLong eventIdCounter = new AtomicLong(0); - Multi sseEvents = Multi.createFrom().publisher(finalStreamingResponse.getPublisher()) - .map(json -> SseFormatter.formatJsonAsSSE(json, eventIdCounter.getAndIncrement())); - // Write SSE-formatted strings to HTTP response - MultiSseSupport.writeSseStrings(sseEvents, rc, context); - }); - } - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void CreateTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { - String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - HTTPRestResponse response = null; - try { - if (taskId == null || taskId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else { - response = jsonRestHandler.createTaskPushNotificationConfiguration(context, extractTenant(rc), body, taskId); - } - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^\\/]+)", order = 2, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) - public void getTaskPushNotificationConfiguration(RoutingContext rc) { - String taskId = rc.pathParam("taskId"); - String configId = rc.pathParam("configId"); - ServerCallContext context = createCallContext(rc, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - HTTPRestResponse response = null; - try { - if (taskId == null || taskId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else if (configId == null || configId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad configuration id")); - }else { - response = jsonRestHandler.getTaskPushNotificationConfiguration(context, extractTenant(rc), taskId, configId); - } - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/?$", order = 3, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) - public void listTaskPushNotificationConfigurations(RoutingContext rc) { - String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - HTTPRestResponse response = null; - try { - if (taskId == null || taskId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else { - int pageSize = 0; - if (rc.request().params().contains(PAGE_SIZE_PARAM)) { - pageSize = Integer.parseInt(rc.request().params().get(PAGE_SIZE_PARAM)); - } - String pageToken = ""; - if (rc.request().params().contains(PAGE_TOKEN_PARAM)) { - pageToken = Utils.defaultIfNull(rc.request().params().get(PAGE_TOKEN_PARAM), ""); - } - response = jsonRestHandler.listTaskPushNotificationConfigurations(context, extractTenant(rc), taskId, pageSize, pageToken); - } - } catch (NumberFormatException e) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad " + PAGE_SIZE_PARAM)); - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/(?[^/]+)", order = 1, methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { - String taskId = rc.pathParam("taskId"); - String configId = rc.pathParam("configId"); - ServerCallContext context = createCallContext(rc, DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - HTTPRestResponse response = null; - try { - if (taskId == null || taskId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad task id")); - } else if (configId == null || configId.isEmpty()) { - response = jsonRestHandler.createErrorResponse(new InvalidParamsError("bad config id")); - } else { - response = jsonRestHandler.deleteTaskPushNotificationConfiguration(context, extractTenant(rc), taskId, configId); - } - } catch (Throwable t) { - response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); - } finally { - sendResponse(rc, response); - } - } - - private String extractTenant(RoutingContext rc) { - String tenantPath = rc.pathParam("tenant"); - if (tenantPath == null || tenantPath.isBlank()) { - return ""; - } - if (tenantPath.startsWith("/")) { - tenantPath = tenantPath.substring(1); - } - if (tenantPath.endsWith("/")) { - tenantPath = tenantPath.substring(0, tenantPath.length() - 1); - } - return tenantPath; - } - - /** - * /** - * Handles incoming GET requests to the agent card endpoint. - * Returns the agent card in JSON format. - * - * @param rc the routing context - */ - @Route(path = "/.well-known/agent-card.json", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) - @PermitAll - public void getAgentCard(RoutingContext rc) { - HTTPRestResponse response = jsonRestHandler.getAgentCard(); - sendResponse(rc, response); - } - - @Route(regex = "^\\/(?[^\\/]*\\/?)extendedAgentCard$", order = 1, methods = Route.HttpMethod.GET, produces = APPLICATION_JSON) - public void getExtendedAgentCard(RoutingContext rc) { - HTTPRestResponse response = jsonRestHandler.getExtendedAgentCard(createCallContext(rc, GET_EXTENDED_AGENT_CARD_METHOD), extractTenant(rc)); - sendResponse(rc, response); - } - - @Route(path = "^/.*", order = 100, methods = {Route.HttpMethod.DELETE, Route.HttpMethod.GET, Route.HttpMethod.HEAD, Route.HttpMethod.OPTIONS, Route.HttpMethod.POST, Route.HttpMethod.PUT}, produces = APPLICATION_JSON) - public void methodNotFoundMessage(RoutingContext rc) { - HTTPRestResponse response = jsonRestHandler.createErrorResponse(new MethodNotFoundError()); - sendResponse(rc, response); - } - - static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { - streamingMultiSseSupportSubscribedRunnable = runnable; - } - - private ServerCallContext createCallContext(RoutingContext rc, String jsonRpcMethodName) { - if (callContextFactory.isUnsatisfied()) { - User user; - if (rc.user() == null) { - user = UnauthenticatedUser.INSTANCE; - } else { - user = new User() { - @Override - public boolean isAuthenticated() { - if (rc.userContext() != null) { - return rc.userContext().authenticated(); - } - return false; - } - - @Override - public String getUsername() { - if (rc.user() != null && rc.user().subject() != null) { - return rc.user().subject(); - } - return ""; - } - }; - } - Map state = new HashMap<>(); - // TODO Python's impl has - // state['auth'] = request.auth - // in jsonrpc_app.py. Figure out what this maps to in what Vert.X gives us - - Map headers = new HashMap<>(); - Set headerNames = rc.request().headers().names(); - headerNames.forEach(name -> headers.put(name, rc.request().getHeader(name))); - state.put(HEADERS_KEY, headers); - state.put(METHOD_NAME_KEY, jsonRpcMethodName); - state.put(TENANT_KEY, extractTenant(rc)); - state.put(TRANSPORT_KEY, TransportProtocol.HTTP_JSON); - - // Extract requested protocol version from X-A2A-Version header - String requestedVersion = rc.request().getHeader(A2AHeaders.X_A2A_VERSION); - - // Extract requested extensions from X-A2A-Extensions header - List extensionHeaderValues = rc.request().headers().getAll(A2AHeaders.X_A2A_EXTENSIONS); - Set requestedExtensions = A2AExtensions.getRequestedExtensions(extensionHeaderValues); - - return new ServerCallContext(user, state, requestedExtensions, requestedVersion); - } else { - CallContextFactory builder = callContextFactory.get(); - return builder.build(rc); - } - } - - /** - * Simplified SSE support for Vert.x/Quarkus. - *

- * This class only handles HTTP-specific concerns (writing to response, backpressure, disconnect). - * SSE formatting and JSON serialization are handled by {@link SseFormatter}. - */ - private static class MultiSseSupport { - private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MultiSseSupport.class); - - private MultiSseSupport() { - // Avoid direct instantiation. - } - - /** - * Write SSE-formatted strings to HTTP response. - * - * @param sseStrings Multi stream of SSE-formatted strings (from SseFormatter) - * @param rc Vert.x routing context - * @param context A2A server call context (for EventConsumer cancellation) - */ - public static void writeSseStrings(Multi sseStrings, RoutingContext rc, ServerCallContext context) { - HttpServerResponse response = rc.response(); - - sseStrings.subscribe().withSubscriber(new Flow.Subscriber() { - Flow.@Nullable Subscription upstream; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.upstream = subscription; - this.upstream.request(1); - - // Detect client disconnect and call EventConsumer.cancel() directly - response.closeHandler(v -> { - logger.debug("REST SSE connection closed by client, calling EventConsumer.cancel() to stop polling loop"); - context.invokeEventConsumerCancelCallback(); - subscription.cancel(); - }); - - // Notify tests that we are subscribed - Runnable runnable = streamingMultiSseSupportSubscribedRunnable; - if (runnable != null) { - runnable.run(); - } - } - - @Override - public void onNext(String sseEvent) { - // Set SSE headers on first event - if (response.bytesWritten() == 0) { - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - // Additional SSE headers to prevent buffering - headers.set("Cache-Control", "no-cache"); - headers.set("X-Accel-Buffering", "no"); // Disable nginx buffering - response.setChunked(true); - - // CRITICAL: Disable write queue max size to prevent buffering - // Vert.x buffers writes by default - we need immediate flushing for SSE - response.setWriteQueueMaxSize(1); // Force immediate flush - - // Send initial SSE comment to kickstart the stream - // This forces Vert.x to send headers and start the stream immediately - response.write(": SSE stream started\n\n"); - } - - // Write SSE-formatted string to response - response.write(Buffer.buffer(sseEvent), new Handler>() { - @Override - public void handle(AsyncResult ar) { - if (ar.failed()) { - // Client disconnected or write failed - cancel upstream to stop EventConsumer - // NullAway: upstream is guaranteed non-null after onSubscribe - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(ar.cause()); - } else { - // NullAway: upstream is guaranteed non-null after onSubscribe - java.util.Objects.requireNonNull(upstream).request(1); - } - } - }); - } - - @Override - public void onError(Throwable throwable) { - // Cancel upstream to stop EventConsumer when error occurs - // NullAway: upstream is guaranteed non-null after onSubscribe - java.util.Objects.requireNonNull(upstream).cancel(); - rc.fail(throwable); - } - - @Override - public void onComplete() { - if (response.bytesWritten() == 0) { - // No events written - still set SSE content type - MultiMap headers = response.headers(); - if (headers.get(CONTENT_TYPE) == null) { - headers.set(CONTENT_TYPE, SERVER_SENT_EVENTS); - } - } - response.end(); - } - }); - } - } - -} diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java deleted file mode 100644 index 7aa5caf5e..000000000 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/CallContextFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import io.a2a.server.ServerCallContext; -import io.vertx.ext.web.RoutingContext; - -public interface CallContextFactory { - ServerCallContext build(RoutingContext rc); -} diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java deleted file mode 100644 index ee9d3ae98..000000000 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/QuarkusRestTransportMetadata.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; - -public class QuarkusRestTransportMetadata implements TransportMetadata { - @Override - public String getTransportProtocol() { - return TransportProtocol.HTTP_JSON.asString(); - } -} diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java deleted file mode 100644 index 00ca87bd6..000000000 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.server.rest.quarkus; - -import org.jspecify.annotations.NullMarked; - diff --git a/reference/rest/src/main/resources/META-INF/beans.xml b/reference/rest/src/main/resources/META-INF/beans.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/reference/rest/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata b/reference/rest/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index cb50024df..000000000 --- a/reference/rest/src/main/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1 +0,0 @@ -io.a2a.server.rest.quarkus.QuarkusRestTransportMetadata \ No newline at end of file diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java deleted file mode 100644 index ce3c140cc..000000000 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java +++ /dev/null @@ -1,305 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; -import static io.a2a.transport.rest.context.RestContextKeys.METHOD_NAME_KEY; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.concurrent.Executor; - -import jakarta.enterprise.inject.Instance; - -import io.a2a.server.ServerCallContext; -import io.a2a.transport.rest.handler.RestHandler; -import io.a2a.transport.rest.handler.RestHandler.HTTPRestResponse; -import io.vertx.core.Future; -import io.vertx.core.MultiMap; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RequestBody; -import io.vertx.ext.web.RoutingContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -/** - * Unit test for A2AServerRoutes that verifies the method names are properly set - * in the ServerCallContext for all route handlers. - */ -public class A2AServerRoutesTest { - - private A2AServerRoutes routes; - private RestHandler mockRestHandler; - private Executor mockExecutor; - private Instance mockCallContextFactory; - private RoutingContext mockRoutingContext; - private HttpServerRequest mockRequest; - private HttpServerResponse mockResponse; - private MultiMap mockHeaders; - private MultiMap mockParams; - private RequestBody mockRequestBody; - - @BeforeEach - public void setUp() { - routes = new A2AServerRoutes(); - mockRestHandler = mock(RestHandler.class); - mockExecutor = mock(Executor.class); - mockCallContextFactory = mock(Instance.class); - mockRoutingContext = mock(RoutingContext.class); - mockRequest = mock(HttpServerRequest.class); - mockResponse = mock(HttpServerResponse.class); - mockHeaders = MultiMap.caseInsensitiveMultiMap(); - mockParams = MultiMap.caseInsensitiveMultiMap(); - mockRequestBody = mock(RequestBody.class); - - // Inject mocks via reflection since we can't use @InjectMocks - setField(routes, "jsonRestHandler", mockRestHandler); - setField(routes, "executor", mockExecutor); - setField(routes, "callContextFactory", mockCallContextFactory); - - // Setup common mock behavior - when(mockCallContextFactory.isUnsatisfied()).thenReturn(true); - when(mockRoutingContext.request()).thenReturn(mockRequest); - when(mockRoutingContext.response()).thenReturn(mockResponse); - when(mockRoutingContext.user()).thenReturn(null); - when(mockRequest.headers()).thenReturn(mockHeaders); - when(mockRequest.params()).thenReturn(mockParams); - when(mockRoutingContext.body()).thenReturn(mockRequestBody); - when(mockRequestBody.asString()).thenReturn("{}"); - when(mockResponse.setStatusCode(any(Integer.class))).thenReturn(mockResponse); - when(mockResponse.putHeader(any(CharSequence.class), any(CharSequence.class))).thenReturn(mockResponse); - when(mockResponse.end()).thenReturn(Future.succeededFuture()); - when(mockResponse.end(anyString())).thenReturn(Future.succeededFuture()); - } - - @Test - public void testSendMessage_MethodNameSetInContext() { - // Arrange - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.sendMessage(any(ServerCallContext.class), anyString(), anyString())).thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.sendMessage("{}", mockRoutingContext); - - // Assert - verify(mockRestHandler).sendMessage(contextCaptor.capture(), anyString(), eq("{}")); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SEND_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testSendMessageStreaming_MethodNameSetInContext() { - // Arrange - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.sendStreamingMessage(any(ServerCallContext.class), anyString(), anyString())) - .thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.sendMessageStreaming("{}", mockRoutingContext); - - // Assert - verify(mockRestHandler).sendStreamingMessage(contextCaptor.capture(), anyString(), eq("{}")); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SEND_STREAMING_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testGetTask_MethodNameSetInContext() { - // Arrange - when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{test:value}"); - when(mockRestHandler.getTask(any(ServerCallContext.class), anyString(), anyString(), any())).thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.getTask(mockRoutingContext); - - // Assert - verify(mockRestHandler).getTask(contextCaptor.capture(), anyString(), eq("task123"), any()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(GET_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testCancelTask_MethodNameSetInContext() { - // Arrange - when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.cancelTask(any(ServerCallContext.class), anyString(), anyString())).thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.cancelTask(mockRoutingContext); - - // Assert - verify(mockRestHandler).cancelTask(contextCaptor.capture(), anyString(), eq("task123")); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testSubscribeTask_MethodNameSetInContext() { - // Arrange - when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.subscribeToTask(any(ServerCallContext.class), anyString(), anyString())) - .thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.subscribeToTask(mockRoutingContext); - - // Assert - verify(mockRestHandler).subscribeToTask(contextCaptor.capture(), anyString(), eq("task123")); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SUBSCRIBE_TO_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testCreateTaskPushNotificationConfiguration_MethodNameSetInContext() { - // Arrange - when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.createTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.CreateTaskPushNotificationConfiguration("{}", mockRoutingContext); - - // Assert - verify(mockRestHandler).createTaskPushNotificationConfiguration(contextCaptor.capture(), anyString(), eq("{}"), eq("task123")); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testGetTaskPushNotificationConfiguration_MethodNameSetInContext() { - // Arrange - when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); - when(mockRoutingContext.pathParam("configId")).thenReturn("config456"); - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.getTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.getTaskPushNotificationConfiguration(mockRoutingContext); - - // Assert - verify(mockRestHandler).getTaskPushNotificationConfiguration(contextCaptor.capture(), anyString(), eq("task123"), - eq("config456")); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testListTaskPushNotificationConfigurations_MethodNameSetInContext() { - // Arrange - when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.listTaskPushNotificationConfigurations(any(ServerCallContext.class), anyString(), anyString(), anyInt(), anyString())) - .thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.listTaskPushNotificationConfigurations(mockRoutingContext); - - // Assert - verify(mockRestHandler).listTaskPushNotificationConfigurations(contextCaptor.capture(), anyString(), eq("task123"), anyInt(), anyString()); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - @Test - public void testDeleteTaskPushNotificationConfiguration_MethodNameSetInContext() { - // Arrange - when(mockRoutingContext.pathParam("taskId")).thenReturn("task123"); - when(mockRoutingContext.pathParam("configId")).thenReturn("config456"); - HTTPRestResponse mockHttpResponse = mock(HTTPRestResponse.class); - when(mockHttpResponse.getStatusCode()).thenReturn(200); - when(mockHttpResponse.getContentType()).thenReturn("application/json"); - when(mockHttpResponse.getBody()).thenReturn("{}"); - when(mockRestHandler.deleteTaskPushNotificationConfiguration(any(ServerCallContext.class), anyString(), anyString(), anyString())).thenReturn(mockHttpResponse); - - ArgumentCaptor contextCaptor = ArgumentCaptor.forClass(ServerCallContext.class); - - // Act - routes.deleteTaskPushNotificationConfiguration(mockRoutingContext); - - // Assert - verify(mockRestHandler).deleteTaskPushNotificationConfiguration(contextCaptor.capture(), anyString(), eq("task123"), - eq("config456")); - ServerCallContext capturedContext = contextCaptor.getValue(); - assertNotNull(capturedContext); - assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); - } - - /** - * Helper method to set a field via reflection for testing purposes. - */ - private void setField(Object target, String fieldName, Object value) { - try { - var field = target.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - field.set(target, value); - } catch (Exception e) { - throw new RuntimeException("Failed to set field: " + fieldName, e); - } - } -} diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java deleted file mode 100644 index 0ce5750b3..000000000 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java +++ /dev/null @@ -1,220 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; -import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; - -import java.util.concurrent.atomic.AtomicInteger; - -import jakarta.annotation.PostConstruct; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.apps.common.TestUtilsBean; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.quarkus.vertx.web.Body; -import io.quarkus.vertx.web.Param; -import io.quarkus.vertx.web.Route; -import io.vertx.ext.web.RoutingContext; - -/** - * Exposes the {@link TestUtilsBean} via REST using Quarkus Reactive Routes - */ -@Singleton -public class A2ATestRoutes { - @Inject - TestUtilsBean testUtilsBean; - - @Inject - A2AServerRoutes a2AServerRoutes; - - AtomicInteger streamingSubscribedCount = new AtomicInteger(0); - - @PostConstruct - public void init() { - A2AServerRoutes.setStreamingMultiSseSupportSubscribedRunnable(() -> streamingSubscribedCount.incrementAndGet()); - } - - - @Route(path = "/test/task", methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void saveTask(@Body String body, RoutingContext rc) { - try { - Task task = JsonUtil.fromJson(body, Task.class); - testUtilsBean.saveTask(task); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.GET}, produces = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) - public void getTask(@Param String taskId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - rc.response() - .setStatusCode(200) - .putHeader(CONTENT_TYPE, APPLICATION_JSON) - .end(JsonUtil.toJson(task)); - - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTask(@Param String taskId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - testUtilsBean.deleteTask(taskId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/ensure/:taskId", methods = {Route.HttpMethod.POST}) - public void ensureTaskQueue(@Param String taskId, RoutingContext rc) { - try { - testUtilsBean.ensureQueue(taskId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/enqueueTaskStatusUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskStatusUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { - - try { - TaskStatusUpdateEvent event = JsonUtil.fromJson(body, TaskStatusUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/queue/enqueueTaskArtifactUpdateEvent/:taskId", methods = {Route.HttpMethod.POST}) - public void enqueueTaskArtifactUpdateEvent(@Param String taskId, @Body String body, RoutingContext rc) { - - try { - TaskArtifactUpdateEvent event = JsonUtil.fromJson(body, TaskArtifactUpdateEvent.class); - testUtilsBean.enqueueEvent(taskId, event); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/streamingSubscribedCount", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getStreamingSubscribedCount(RoutingContext rc) { - rc.response() - .setStatusCode(200) - .end(String.valueOf(streamingSubscribedCount.get())); - } - - @Route(path = "/test/queue/childCount/:taskId", methods = {Route.HttpMethod.GET}, produces = {TEXT_PLAIN}) - public void getChildQueueCount(@Param String taskId, RoutingContext rc) { - int count = testUtilsBean.getChildQueueCount(taskId); - rc.response() - .setStatusCode(200) - .end(String.valueOf(count)); - } - - @Route(path = "/test/task/:taskId/config/:configId", methods = {Route.HttpMethod.DELETE}, type = Route.HandlerType.BLOCKING) - public void deleteTaskPushNotificationConfig(@Param String taskId, @Param String configId, RoutingContext rc) { - try { - Task task = testUtilsBean.getTask(taskId); - if (task == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - testUtilsBean.deleteTaskPushNotificationConfig(taskId, configId); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - @Route(path = "/test/task/:taskId", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void saveTaskPushNotificationConfig(@Param String taskId, @Body String body, RoutingContext rc) { - try { - PushNotificationConfig notificationConfig = JsonUtil.fromJson(body, PushNotificationConfig.class); - if (notificationConfig == null) { - rc.response() - .setStatusCode(404) - .end(); - return; - } - testUtilsBean.saveTaskPushNotificationConfig(taskId, notificationConfig); - rc.response() - .setStatusCode(200) - .end(); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - /** - * REST endpoint to wait for child queue count to stabilize. - * Waits for the specified task's child queue count to match expectedCount for 3 consecutive - * checks (150ms total), ensuring EventConsumer polling loops have started. - * - * @param taskId the task ID whose child queues to monitor - * @param expectedCountStr the expected number of active child queues (as string) - * @param timeoutMsStr maximum time to wait in milliseconds (as string) - * @param rc the Vert.x routing context - */ - @Route(path = "/test/queue/awaitChildCountStable/:taskId/:expectedCount/:timeoutMs", methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) - public void awaitChildQueueCountStable(@Param("taskId") String taskId, @Param("expectedCount") String expectedCountStr, @Param("timeoutMs") String timeoutMsStr, RoutingContext rc) { - try { - int expectedCount = Integer.parseInt(expectedCountStr); - long timeoutMs = Long.parseLong(timeoutMsStr); - boolean stable = testUtilsBean.awaitChildQueueCountStable(taskId, expectedCount, timeoutMs); - rc.response() - .setStatusCode(200) - .end(String.valueOf(stable)); - } catch (Throwable t) { - errorResponse(t, rc); - } - } - - private void errorResponse(Throwable t, RoutingContext rc) { - t.printStackTrace(); - rc.response() - .setStatusCode(500) - .putHeader(CONTENT_TYPE, TEXT_PLAIN) - .end(); - } - -} diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestJdkTest.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestJdkTest.java deleted file mode 100644 index 74cdc958f..000000000 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestJdkTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.JdkA2AHttpClient; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; -import io.quarkus.test.junit.QuarkusTest; - -@QuarkusTest -public class QuarkusA2ARestJdkTest extends QuarkusA2ARestTest { - - @Override - protected void configureTransport(ClientBuilder builder) { - builder.withTransport(RestTransport.class, new RestTransportConfigBuilder().httpClient(new JdkA2AHttpClient())); - } -} diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java deleted file mode 100644 index 0940c5afc..000000000 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; - -import io.a2a.client.ClientBuilder; -import io.a2a.server.apps.common.AbstractA2AServerTest; -import io.a2a.spec.TransportProtocol; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public abstract class QuarkusA2ARestTest extends AbstractA2AServerTest { - - public QuarkusA2ARestTest() { - super(8081); - } - - @Override - protected String getTransportProtocol() { - return TransportProtocol.HTTP_JSON.asString(); - } - - @Override - protected String getTransportUrl() { - return "http://localhost:8081"; - } - - @Override - protected abstract void configureTransport(ClientBuilder builder); - - @Test - public void testMethodNotFound() throws Exception { - // Create the client - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - // Create the request - HttpRequest.Builder builder = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/message:send")) - .PUT(HttpRequest.BodyPublishers.ofString("test")) - .header("Content-Type", APPLICATION_JSON); - HttpResponse response = client.send(builder.build(), HttpResponse.BodyHandlers.ofString()); - Assertions.assertEquals(405, response.statusCode()); - builder = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/message:send")) - .DELETE() - .header("Content-Type", APPLICATION_JSON); - response = client.send(builder.build(), HttpResponse.BodyHandlers.ofString()); - Assertions.assertEquals(405, response.statusCode()); - } -} diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestVertxTest.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestVertxTest.java deleted file mode 100644 index 106c52fd2..000000000 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/QuarkusA2ARestVertxTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.a2a.server.rest.quarkus; - -import io.a2a.client.ClientBuilder; -import io.a2a.client.http.VertxA2AHttpClient; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; -import io.quarkus.test.junit.QuarkusTest; -import io.vertx.core.Vertx; -import jakarta.inject.Inject; - -@QuarkusTest -public class QuarkusA2ARestVertxTest extends QuarkusA2ARestTest { - - @Inject - Vertx vertx; - - @Override - protected void configureTransport(ClientBuilder builder) { - builder.withTransport(RestTransport.class, new RestTransportConfigBuilder().httpClient(new VertxA2AHttpClient(vertx))); - } -} diff --git a/reference/rest/src/test/resources/a2a-requesthandler-test.properties b/reference/rest/src/test/resources/a2a-requesthandler-test.properties deleted file mode 100644 index 61696e179..000000000 --- a/reference/rest/src/test/resources/a2a-requesthandler-test.properties +++ /dev/null @@ -1 +0,0 @@ -preferred-transport=HTTP+JSON diff --git a/reference/rest/src/test/resources/application.properties b/reference/rest/src/test/resources/application.properties deleted file mode 100644 index d3366bece..000000000 --- a/reference/rest/src/test/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -quarkus.arc.selected-alternatives=io.a2a.server.apps.common.TestHttpClient \ No newline at end of file diff --git a/server-common/pom.xml b/server-common/pom.xml deleted file mode 100644 index 378337b9d..000000000 --- a/server-common/pom.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - a2a-java-sdk-server-common - - jar - - Java SDK A2A Core - Java SDK for the Agent2Agent Protocol (A2A) - Server Common - - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-spec-grpc - - - ${project.groupId} - a2a-java-sdk-http-client - - - ${project.groupId} - a2a-java-sdk-http-client-vertx - provided - - - ${project.groupId} - a2a-java-sdk-client-transport-jsonrpc - - - io.smallrye.reactive - mutiny-zero - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - org.slf4j - slf4j-api - - - io.quarkus - quarkus-arc - test - - - org.jboss.logging - jboss-logging - - - org.jboss.logmanager - jboss-logmanager - - - org.jboss.threads - jboss-threads - - - org.jboss.slf4j - slf4j-jboss-logmanager - - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.mockito - mockito-core - test - - - ch.qos.logback - logback-classic - test - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - - diff --git a/server-common/src/main/java/io/a2a/server/AgentCardValidator.java b/server-common/src/main/java/io/a2a/server/AgentCardValidator.java deleted file mode 100644 index cd499359c..000000000 --- a/server-common/src/main/java/io/a2a/server/AgentCardValidator.java +++ /dev/null @@ -1,167 +0,0 @@ -package io.a2a.server; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.ServiceLoader; -import java.util.Set; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; - -/** - * Validates AgentCard transport configuration against available transport endpoints. - */ -public class AgentCardValidator { - - private static final Logger LOGGER = Logger.getLogger(AgentCardValidator.class.getName()); - - // Properties to turn off validation globally, or per known transport - public static final String SKIP_PROPERTY = "io.a2a.transport.skipValidation"; - public static final String SKIP_JSONRPC_PROPERTY = "io.a2a.transport.jsonrpc.skipValidation"; - public static final String SKIP_GRPC_PROPERTY = "io.a2a.transport.grpc.skipValidation"; - public static final String SKIP_REST_PROPERTY = "io.a2a.transport.rest.skipValidation"; - - /** - * Validates the transport configuration of an AgentCard against available transports found on the classpath. - * Logs warnings for missing transports and errors for unsupported transports. - * - * @param agentCard the agent card to validate - */ - public static void validateTransportConfiguration(AgentCard agentCard) { - validateTransportConfiguration(agentCard, getAvailableTransports()); - } - - /** - * Validates the transport configuration of an AgentCard against a given set of available transports. - * This method is package-private for testability. - * - * @param agentCard the agent card to validate - * @param availableTransports the set of available transport protocols - */ - static void validateTransportConfiguration(AgentCard agentCard, Set availableTransports) { - boolean skip = Boolean.getBoolean(SKIP_PROPERTY); - if (skip) { - return; - } - - Set agentCardTransports = getAgentCardTransports(agentCard); - Set filteredAvailableTransports = filterSkippedTransports(availableTransports); - Set filteredAgentCardTransports = filterSkippedTransports(agentCardTransports); - - // Check for missing transports (warn if AgentCard doesn't include all available transports) - Set missingTransports = filteredAvailableTransports.stream() - .filter(transport -> !filteredAgentCardTransports.contains(transport)) - .collect(Collectors.toSet()); - - if (!missingTransports.isEmpty()) { - LOGGER.warning(String.format( - "AgentCard does not include all available transports. Missing: %s. " + - "Available transports: %s. AgentCard transports: %s", - formatTransports(missingTransports), - formatTransports(filteredAvailableTransports), - formatTransports(filteredAgentCardTransports) - )); - } - - // Check for unsupported transports (error if AgentCard specifies unavailable transports) - Set unsupportedTransports = filteredAgentCardTransports.stream() - .filter(transport -> !filteredAvailableTransports.contains(transport)) - .collect(Collectors.toSet()); - - if (!unsupportedTransports.isEmpty()) { - String errorMessage = String.format( - "AgentCard specifies transport interfaces for unavailable transports: %s. " + - "Available transports: %s. Consider removing these interfaces or adding the required transport dependencies.", - formatTransports(unsupportedTransports), - formatTransports(filteredAvailableTransports) - ); - LOGGER.severe(errorMessage); - - // Following the GitHub issue suggestion to use an error instead of warning - throw new IllegalStateException(errorMessage); - } - - // Validation no longer needed - supportedInterfaces is now the single source of truth - // The first entry in supportedInterfaces is the preferred interface - } - - /** - * Extracts all transport protocols specified in the AgentCard. - * - * @param agentCard the agent card to analyze - * @return set of transport protocols specified in the agent card - */ - private static Set getAgentCardTransports(AgentCard agentCard) { - List transportStrings = new ArrayList<>(); - - // Get all transports from supportedInterfaces - if (agentCard.supportedInterfaces() != null) { - for (AgentInterface agentInterface : agentCard.supportedInterfaces()) { - if (agentInterface.protocolBinding() != null) { - transportStrings.add(agentInterface.protocolBinding()); - } - } - } - - return new HashSet<>(transportStrings); - } - - /** - * Formats a set of transport protocols for logging. - * - * @param transports the transport protocols to format - * @return formatted string representation - */ - private static String formatTransports(Set transports) { - return transports.stream() - .collect(Collectors.joining(", ", "[", "]")); - } - - /** - * Filters out transports that have been configured to skip validation. - * - * @param transports the set of transport protocols to filter - * @return filtered set with skipped transports removed - */ - private static Set filterSkippedTransports(Set transports) { - return transports.stream() - .filter(transport -> !isTransportSkipped(transport)) - .collect(Collectors.toSet()); - } - - /** - * Checks if validation should be skipped for a specific transport. - * - * @param transport the transport protocol to check - * @return true if validation should be skipped for this transport - */ - private static boolean isTransportSkipped(String transport) { - if (transport.equals(TransportProtocol.JSONRPC.asString())) { - return Boolean.getBoolean(SKIP_JSONRPC_PROPERTY); - } else if (transport.equals(TransportProtocol.GRPC.asString())){ - return Boolean.getBoolean(SKIP_GRPC_PROPERTY); - } else if (transport.equals(TransportProtocol.HTTP_JSON.asString())) { - return Boolean.getBoolean(SKIP_REST_PROPERTY); - } - return false; - } - - /** - * Discovers available transport endpoints using ServiceLoader. - * This searches the classpath for implementations of TransportMetadata. - * - * @return set of available transport protocols - */ - private static Set getAvailableTransports() { - return ServiceLoader.load(TransportMetadata.class) - .stream() - .map(ServiceLoader.Provider::get) - .filter(TransportMetadata::isAvailable) - .map(TransportMetadata::getTransportProtocol) - .collect(Collectors.toSet()); - } -} diff --git a/server-common/src/main/java/io/a2a/server/ExtendedAgentCard.java b/server-common/src/main/java/io/a2a/server/ExtendedAgentCard.java deleted file mode 100644 index c9cc7eaf0..000000000 --- a/server-common/src/main/java/io/a2a/server/ExtendedAgentCard.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.server; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.inject.Qualifier; - -@Qualifier -@Retention(RUNTIME) -@Target({FIELD, TYPE, METHOD, PARAMETER}) -public @interface ExtendedAgentCard { -} diff --git a/server-common/src/main/java/io/a2a/server/JSONRPCException.java b/server-common/src/main/java/io/a2a/server/JSONRPCException.java deleted file mode 100644 index 3911355d6..000000000 --- a/server-common/src/main/java/io/a2a/server/JSONRPCException.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.a2a.server; - -import io.a2a.spec.A2AError; - -/** - * Exception wrapper for JSON-RPC protocol errors. - *

- * This exception encapsulates a {@link A2AError} for handling - * protocol-level errors during JSON-RPC request processing. - *

- */ -public class JSONRPCException extends Exception{ - private final A2AError error; - - /** - * Creates a JSONRPCException wrapping the specified error. - * - * @param error the JSON-RPC error - */ - public JSONRPCException(A2AError error) { - this.error = error; - } - - /** - * Returns the wrapped JSON-RPC error. - * - * @return the JSON-RPC error - */ - public A2AError getError() { - return error; - } -} diff --git a/server-common/src/main/java/io/a2a/server/PublicAgentCard.java b/server-common/src/main/java/io/a2a/server/PublicAgentCard.java deleted file mode 100644 index 68c670bbe..000000000 --- a/server-common/src/main/java/io/a2a/server/PublicAgentCard.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.server; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import jakarta.inject.Qualifier; - -@Qualifier -@Retention(RUNTIME) -@Target({FIELD, TYPE, METHOD, PARAMETER}) -public @interface PublicAgentCard { -} diff --git a/server-common/src/main/java/io/a2a/server/ServerCallContext.java b/server-common/src/main/java/io/a2a/server/ServerCallContext.java deleted file mode 100644 index 21a9e790b..000000000 --- a/server-common/src/main/java/io/a2a/server/ServerCallContext.java +++ /dev/null @@ -1,134 +0,0 @@ -package io.a2a.server; - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import io.a2a.server.auth.User; -import org.jspecify.annotations.Nullable; - -public class ServerCallContext { - /** - * Key for transport protocol type in the state map. - * Value should be a {@link io.a2a.spec.TransportProtocol} instance. - */ - public static final String TRANSPORT_KEY = "transport"; - - // TODO Not totally sure yet about these field types - private final Map modelConfig = new ConcurrentHashMap<>(); - private final Map state; - private final User user; - private final Set requestedExtensions; - private final Set activatedExtensions; - private final @Nullable String requestedProtocolVersion; - private volatile @Nullable Runnable eventConsumerCancelCallback; - - public ServerCallContext(User user, Map state, Set requestedExtensions) { - this(user, state, requestedExtensions, null); - } - - public ServerCallContext(User user, Map state, Set requestedExtensions, @Nullable String requestedProtocolVersion) { - this.user = user; - this.state = state; - this.requestedExtensions = new HashSet<>(requestedExtensions); - this.activatedExtensions = new HashSet<>(); // Always starts empty, populated later by application code - this.requestedProtocolVersion = requestedProtocolVersion; - } - - public Map getState() { - return state; - } - - public User getUser() { - return user; - } - - public Set getRequestedExtensions() { - return new HashSet<>(requestedExtensions); - } - - public Set getActivatedExtensions() { - return new HashSet<>(activatedExtensions); - } - - public void activateExtension(String extensionUri) { - activatedExtensions.add(extensionUri); - } - - public void deactivateExtension(String extensionUri) { - activatedExtensions.remove(extensionUri); - } - - public boolean isExtensionActivated(String extensionUri) { - return activatedExtensions.contains(extensionUri); - } - - public boolean isExtensionRequested(String extensionUri) { - return requestedExtensions.contains(extensionUri); - } - - public @Nullable String getRequestedProtocolVersion() { - return requestedProtocolVersion; - } - - /** - * Sets the callback to be invoked when the client disconnects or the call is cancelled. - *

- * This callback is typically used to stop the EventConsumer polling loop when a client - * disconnects from a streaming endpoint. The callback is invoked by transport layers - * (JSON-RPC over HTTP/SSE, REST over HTTP/SSE, gRPC streaming) when they detect that - * the client has closed the connection. - *

- *

- * Thread Safety: The callback may be invoked from any thread, depending - * on the transport implementation. Implementations should be thread-safe. - *

- * Example Usage: - *
{@code
-     * EventConsumer consumer = new EventConsumer(queue);
-     * context.setEventConsumerCancelCallback(consumer::cancel);
-     * }
- * - * @param callback the callback to invoke on client disconnect, or null to clear any existing callback - * @see #invokeEventConsumerCancelCallback() - */ - public void setEventConsumerCancelCallback(@Nullable Runnable callback) { - this.eventConsumerCancelCallback = callback; - } - - /** - * Invokes the EventConsumer cancel callback if one has been set. - *

- * This method is called by transport layers when a client disconnects or cancels a - * streaming request. It triggers the callback registered via - * {@link #setEventConsumerCancelCallback(Runnable)}, which typically stops the - * EventConsumer polling loop. - *

- *

- * Transport-Specific Behavior: - *

- *
    - *
  • JSON-RPC/REST over HTTP/SSE: Called from Vert.x - * {@code HttpServerResponse.closeHandler()} when the SSE connection is closed
  • - *
  • gRPC streaming: Called from gRPC - * {@code Context.CancellationListener.cancelled()} when the call is cancelled
  • - *
- *

- * Thread Safety: This method is thread-safe. The callback is stored - * in a volatile field and null-checked before invocation to prevent race conditions. - *

- *

- * If no callback has been set, this method does nothing (no-op). - *

- * - * @see #setEventConsumerCancelCallback(Runnable) - * @see io.a2a.server.events.EventConsumer#cancel() - */ - public void invokeEventConsumerCancelCallback() { - Runnable callback = this.eventConsumerCancelCallback; - if (callback != null) { - callback.run(); - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/TransportMetadata.java b/server-common/src/main/java/io/a2a/server/TransportMetadata.java deleted file mode 100644 index 207ebcc67..000000000 --- a/server-common/src/main/java/io/a2a/server/TransportMetadata.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.a2a.server; - - -/** - * Interface for transport endpoint implementations to provide metadata about their transport. - * This is used by the validation system to discover available transports on the classpath. - */ -public interface TransportMetadata { - - /** - * Returns the transport protocol this endpoint supports. - * - * @return the transport protocol - */ - String getTransportProtocol(); - - /** - * Checks if this transport endpoint is currently available/functional. - * This can be used for runtime availability checks beyond just classpath presence. - * - * @return true if the transport is available, false otherwise - */ - default boolean isAvailable() { - return true; - } -} \ No newline at end of file diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java b/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java deleted file mode 100644 index 08d6b56d9..000000000 --- a/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java +++ /dev/null @@ -1,151 +0,0 @@ -package io.a2a.server.agentexecution; - -import io.a2a.server.events.EventQueue; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AError; - -/** - * Core business logic interface for implementing A2A agent functionality. - *

- * This is the primary extension point where agent developers implement their agent's behavior - - * LLM interactions, data processing, external API calls, or any custom logic. Along with an - * {@link io.a2a.spec.AgentCard}, implementing this interface is the minimum requirement to - * create a functioning A2A agent. - *

- * - *

Lifecycle

- * The {@link io.a2a.server.requesthandlers.DefaultRequestHandler} executes AgentExecutor methods - * asynchronously in a background thread pool when requests arrive from transport layers. - * Your implementation should: - *
    - *
  • Use the {@link AgentEmitter} to send messages, update task status, and stream artifacts
  • - *
  • Handle cancellation via the {@link #cancel(RequestContext, AgentEmitter)} method
  • - *
  • Be thread-safe if maintaining state across invocations
  • - *
- * - *

Threading Model

- *
    - *
  • {@code execute()} runs in the agent-executor thread pool (background thread)
  • - *
  • Events are consumed by Vert.x worker threads that return responses to clients
  • - *
  • Don't block waiting for events to be consumed - enqueue and return
  • - *
  • Multiple {@code execute()} calls may run concurrently for different tasks
  • - *
- * - *

CDI Integration

- * Provide your AgentExecutor via CDI producer: - *
{@code
- * @ApplicationScoped
- * public class MyAgentExecutorProducer {
- *     @Inject
- *     MyService myService;  // Your business logic
- *
- *     @Produces
- *     public AgentExecutor agentExecutor() {
- *         return new MyAgentExecutor(myService);
- *     }
- * }
- * }
- * - *

Example Implementation

- *
{@code
- * public class WeatherAgentExecutor implements AgentExecutor {
- *     private final WeatherService weatherService;
- *
- *     public WeatherAgentExecutor(WeatherService weatherService) {
- *         this.weatherService = weatherService;
- *     }
- *
- *     @Override
- *     public void execute(RequestContext context, AgentEmitter emitter) {
- *         // Initialize task if this is a new conversation
- *         if (context.getTask() == null) {
- *             emitter.submit();
- *         }
- *         emitter.startWork();
- *
- *         // Extract user input from the message
- *         String userMessage = context.getUserInput("\n");
- *
- *         // Process request (your business logic)
- *         String weatherData = weatherService.getWeather(userMessage);
- *
- *         // Return result as artifact
- *         emitter.addArtifact(List.of(new TextPart(weatherData, null)));
- *         emitter.complete();
- *     }
- *
- *     @Override
- *     public void cancel(RequestContext context, AgentEmitter emitter) {
- *         // Clean up resources and mark as canceled
- *         emitter.cancel();
- *     }
- * }
- * }
- * - *

Streaming Results

- * For long-running operations or LLM streaming, enqueue multiple artifacts: - *
{@code
- * emitter.startWork();
- * for (String chunk : llmService.stream(userInput)) {
- *     emitter.addArtifact(List.of(new TextPart(chunk, null)));
- * }
- * emitter.complete();  // Final event closes the queue
- * }
- * - * @see RequestContext - * @see AgentEmitter - * @see io.a2a.server.requesthandlers.DefaultRequestHandler - * @see io.a2a.spec.AgentCard - */ -public interface AgentExecutor { - /** - * Executes the agent's business logic for a message. - *

- * Called asynchronously by {@link io.a2a.server.requesthandlers.DefaultRequestHandler} - * in a background thread when a client sends a message. Enqueue events to the queue as - * processing progresses. The queue remains open until you enqueue a final event - * (COMPLETED, FAILED, or CANCELED state). - *

- *

- * Important: Don't throw exceptions for business logic errors. Instead, use - * {@code emitter.fail(errorMessage)} to communicate failures to the client gracefully. - * Only throw {@link A2AError} for truly exceptional conditions. - *

- * - * @param context the request context containing the message, task state, and configuration - * @param emitter the agent emitter for sending messages, updating status, and streaming artifacts - * @throws A2AError if execution fails catastrophically (exception propagates to client) - */ - void execute(RequestContext context, AgentEmitter emitter) throws A2AError; - - /** - * Cancels an ongoing agent execution. - *

- * Called when a client requests task cancellation via the cancelTask operation. - * You should: - *

    - *
  • Stop any ongoing work (interrupt LLM calls, cancel API requests)
  • - *
  • Enqueue a CANCELED status event (typically via {@code emitter.cancel()})
  • - *
  • Clean up resources (close connections, release locks)
  • - *
- *

- * Note: The {@link #execute(RequestContext, AgentEmitter)} method may still be - * running on another thread. Use appropriate synchronization or interruption mechanisms - * if your agent maintains cancellable state. - *

- * Error Handling: - *

    - *
  • Throw {@link io.a2a.spec.TaskNotCancelableError} if your agent does not support - * cancellation at all (e.g., fire-and-forget agents)
  • - *
  • Throw {@link A2AError} if cancellation is supported but failed to execute - * (e.g., unable to interrupt running operation)
  • - *
  • Return normally after enqueueing CANCELED event if cancellation succeeds
  • - *
- * - * @param context the request context for the task being canceled - * @param emitter the agent emitter for sending the cancellation event - * @throws io.a2a.spec.TaskNotCancelableError if this agent does not support cancellation - * @throws A2AError if cancellation is supported but failed to execute - */ - void cancel(RequestContext context, AgentEmitter emitter) throws A2AError; -} diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java b/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java deleted file mode 100644 index beee9bf7e..000000000 --- a/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java +++ /dev/null @@ -1,412 +0,0 @@ -package io.a2a.server.agentexecution; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; - -import io.a2a.server.ServerCallContext; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TextPart; -import org.jspecify.annotations.Nullable; - -/** - * Container for request parameters and task state provided to {@link AgentExecutor}. - *

- * This class encapsulates all the information an agent needs to process a request: - * the user's message, existing task state (for continuing conversations), configuration, - * and server call context. It's the primary way agents access request data. - *

- * - *

Key Components

- *
    - *
  • Message: The user's input message with parts (text, images, etc.)
  • - *
  • Task: Existing task state for continuing conversations (null for new conversations)
  • - *
  • TaskId/ContextId: Identifiers for the task and conversation (auto-generated if not provided)
  • - *
  • Configuration: Request settings (blocking mode, push notifications, etc.)
  • - *
  • Related Tasks: Other tasks in the same conversation context
  • - *
- * - *

Common Usage Patterns

- *
{@code
- * public void execute(RequestContext context, AgentEmitter emitter) {
- *     // Check if this is a new conversation or continuation
- *     Task existingTask = context.getTask();
- *     if (existingTask == null) {
- *         // New conversation - initialize
- *     } else {
- *         // Continuing conversation - access history
- *         List history = existingTask.history();
- *     }
- *
- *     // Extract user input
- *     String userMessage = context.getUserInput("\n");
- *
- *     // Access configuration if needed
- *     MessageSendConfiguration config = context.getConfiguration();
- *     boolean isBlocking = config != null && config.blocking();
- *
- *     // Process and respond...
- * }
- * }
- * - *

Text Extraction Helper

- * The {@link #getUserInput(String)} method is a convenient way to extract text from - * message parts: - *
{@code
- * // Get all text parts joined with newlines
- * String text = context.getUserInput("\n");
- *
- * // Get all text parts joined with spaces
- * String text = context.getUserInput(" ");
- * }
- * - * @see AgentExecutor - * @see Message - * @see Task - * @see MessageSendConfiguration - */ -public class RequestContext { - - private final @Nullable MessageSendParams params; - private final String taskId; - private final String contextId; - private final @Nullable Task task; - private final List relatedTasks; - private final @Nullable ServerCallContext callContext; - - /** - * Constructor with all fields already validated and initialized. - *

- * Note: Use {@link Builder} instead of calling this constructor directly. - * The builder handles ID generation and validation. - *

- * - * @param params the message send parameters (can be null for cancel operations) - * @param taskId the task identifier (must not be null) - * @param contextId the context identifier (must not be null) - * @param task the existing task state (null for new conversations) - * @param relatedTasks other tasks in the same context (must not be null, can be empty) - * @param callContext the server call context (can be null) - */ - private RequestContext( - @Nullable MessageSendParams params, - String taskId, - String contextId, - @Nullable Task task, - List relatedTasks, - @Nullable ServerCallContext callContext) { - this.params = params; - this.taskId = taskId; - this.contextId = contextId; - this.task = task; - this.relatedTasks = relatedTasks; - this.callContext = callContext; - } - - /** - * Returns the task identifier. - *

- * This is auto-generated (UUID) by the builder if not provided by the client - * in the message parameters. This value is never null. - *

- * - * @return the task ID (never null) - */ - public String getTaskId() { - return taskId; - } - - /** - * Returns the conversation context identifier. - *

- * Conversation contexts group related tasks together (e.g., multiple tasks - * in the same user session). This is auto-generated (UUID) by the builder if - * not provided by the client in the message parameters. This value is never null. - *

- * - * @return the context ID (never null) - */ - public String getContextId() { - return contextId; - } - - /** - * Returns the existing task state, if this is a continuation of a conversation. - *

- * For new conversations, this is null. For continuing conversations, contains - * the full task state including history, artifacts, and status. - *

- * Common Pattern: - *

{@code
-     * if (context.getTask() == null) {
-     *     // New conversation - initialize state
-     * } else {
-     *     // Continuing - access previous messages
-     *     List history = context.getTask().history();
-     * }
-     * }
- * - * @return the existing task, or null if this is a new conversation - */ - public @Nullable Task getTask() { - return task; - } - - /** - * Returns other tasks in the same conversation context. - *

- * Useful for multi-task conversations where the agent needs to access - * state from related tasks. - *

- * - * @return unmodifiable list of related tasks (empty if none) - */ - public List getRelatedTasks() { - return Collections.unmodifiableList(relatedTasks); - } - - /** - * Returns the user's message. - *

- * Contains the message parts (text, images, etc.) sent by the client. - * Use {@link #getUserInput(String)} for convenient text extraction. - *

- * - * @return the message, or null if not available - * @see #getUserInput(String) - */ - public @Nullable Message getMessage() { - return params != null ? params.message() : null; - } - - /** - * Returns the request configuration. - *

- * Contains settings like blocking mode, push notification config, etc. - *

- * - * @return the configuration, or null if not provided - */ - public @Nullable MessageSendConfiguration getConfiguration() { - return params != null ? params.configuration() : null; - } - - /** - * Returns the server call context. - *

- * Contains transport-specific information like authentication, headers, etc. - * Most agents don't need this. - *

- * - * @return the call context, or null if not available - */ - public @Nullable ServerCallContext getCallContext() { - return callContext; - } - - /** - * Returns the tenant identifier from the request parameters. - *

- * The tenant is used in multi-tenant environments to identify which - * customer or organization the request belongs to. - *

- * - * @return the tenant identifier, or null if no params or tenant not set - */ - public @Nullable String getTenant() { - return params != null ? params.tenant() : null; - } - - /** - * Extracts all text content from the message and joins with the specified delimiter. - *

- * This is a convenience method for getting text input from messages that may contain - * multiple text parts. Non-text parts (images, etc.) are ignored. - *

- * Examples: - *

{@code
-     * // Join with newlines (common for multi-paragraph input)
-     * String text = context.getUserInput("\n");
-     *
-     * // Join with spaces (common for single-line input)
-     * String text = context.getUserInput(" ");
-     *
-     * // Default delimiter is newline
-     * String text = context.getUserInput(null);  // uses "\n"
-     * }
- * - * @param delimiter the string to insert between text parts (null defaults to "\n") - * @return all text parts joined with delimiter, or empty string if no message - */ - public String getUserInput(String delimiter) { - if (params == null) { - return ""; - } - if (delimiter == null) { - delimiter = "\n"; - } - return getMessageText(params.message(), delimiter); - } - - /** - * Attaches a related task to this context. - *

- * This is primarily used by the framework to populate related tasks after - * construction. Agent implementations should use {@link #getRelatedTasks()} - * to access related tasks. - *

- * - * @param task the task to attach - */ - public void attachRelatedTask(Task task) { - relatedTasks.add(task); - } - - private String getMessageText(Message message, String delimiter) { - List textParts = getTextParts(message.parts()); - return String.join(delimiter, textParts); - } - - private List getTextParts(List> parts) { - return parts.stream() - .filter(part -> part instanceof TextPart) - .map(part -> (TextPart) part) - .map(TextPart::text) - .collect(Collectors.toList()); - } - - /** - * Builder for creating {@link RequestContext} instances. - *

- * The builder handles ID generation and validation automatically: - *

- *
    - *
  • TaskId and ContextId are auto-generated (UUID) if not provided
  • - *
  • IDs are validated against message parameters if both are present
  • - *
  • Message parameters are updated with generated IDs
  • - *
  • Related tasks list is initialized to empty list if null
  • - *
- */ - public static class Builder { - private @Nullable MessageSendParams params; - private @Nullable String taskId; - private @Nullable String contextId; - private @Nullable Task task; - private @Nullable List relatedTasks; - private @Nullable ServerCallContext serverCallContext; - - public Builder setParams(@Nullable MessageSendParams params) { - this.params = params; - return this; - } - - public Builder setTaskId(@Nullable String taskId) { - this.taskId = taskId; - return this; - } - - public Builder setContextId(@Nullable String contextId) { - this.contextId = contextId; - return this; - } - - public Builder setTask(@Nullable Task task) { - this.task = task; - return this; - } - - public Builder setRelatedTasks(@Nullable List relatedTasks) { - this.relatedTasks = relatedTasks; - return this; - } - - public Builder setServerCallContext(@Nullable ServerCallContext serverCallContext) { - this.serverCallContext = serverCallContext; - return this; - } - - public @Nullable MessageSendParams getParams() { - return params; - } - - public @Nullable String getTaskId() { - return taskId; - } - - public @Nullable String getContextId() { - return contextId; - } - - public @Nullable Task getTask() { - return task; - } - - public @Nullable List getRelatedTasks() { - return relatedTasks; - } - - public @Nullable ServerCallContext getServerCallContext() { - return serverCallContext; - } - - /** - * Builds the RequestContext with ID generation and validation. - * - * @return the constructed RequestContext - * @throws InvalidParamsError if taskId or contextId don't match message parameters - */ - public RequestContext build() throws InvalidParamsError { - // 1. Initialize relatedTasks to empty list if null - List finalRelatedTasks = relatedTasks != null ? relatedTasks : new ArrayList<>(); - - // 2. Extract message IDs upfront (or null if no params) - String messageTaskId = params != null ? params.message().taskId() : null; - String messageContextId = params != null ? params.message().contextId() : null; - - // 3. Validate: if both builder and message provide an ID, they must match - if (taskId != null && messageTaskId != null && !taskId.equals(messageTaskId)) { - throw new InvalidParamsError("bad task id"); - } - if (contextId != null && messageContextId != null && !contextId.equals(messageContextId)) { - throw new InvalidParamsError("bad context id"); - } - - // 4. Determine final IDs using coalesce pattern: builder → message → generate - String finalTaskId = taskId != null ? taskId : - messageTaskId != null ? messageTaskId : - UUID.randomUUID().toString(); - - String finalContextId = contextId != null ? contextId : - messageContextId != null ? messageContextId : - UUID.randomUUID().toString(); - - // 5. Update params if message needs to be updated with final IDs - MessageSendParams finalParams = params; - if (params != null && (!finalTaskId.equals(messageTaskId) || !finalContextId.equals(messageContextId))) { - Message updatedMessage = Message.builder(params.message()) - .taskId(finalTaskId) - .contextId(finalContextId) - .build(); - // Preserve all original fields including tenant - finalParams = MessageSendParams.builder() - .message(updatedMessage) - .configuration(params.configuration()) - .metadata(params.metadata()) - .tenant(params.tenant()) - .build(); - } - - // 6. Call constructor with finalized values (IDs guaranteed non-null) - return new RequestContext(finalParams, finalTaskId, finalContextId, - task, finalRelatedTasks, serverCallContext); - } - } - -} diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/SimpleRequestContextBuilder.java b/server-common/src/main/java/io/a2a/server/agentexecution/SimpleRequestContextBuilder.java deleted file mode 100644 index 573d0e879..000000000 --- a/server-common/src/main/java/io/a2a/server/agentexecution/SimpleRequestContextBuilder.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.a2a.server.agentexecution; - -import java.util.ArrayList; -import java.util.List; - -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Task; - -public class SimpleRequestContextBuilder extends RequestContext.Builder { - private final TaskStore taskStore; - private final boolean shouldPopulateReferredTasks; - - public SimpleRequestContextBuilder(TaskStore taskStore, boolean shouldPopulateReferredTasks) { - this.taskStore = taskStore; - this.shouldPopulateReferredTasks = shouldPopulateReferredTasks; - } - - @Override - public RequestContext build() { - List relatedTasks = null; - if (taskStore != null && shouldPopulateReferredTasks && getParams() != null - && getParams().message().referenceTaskIds() != null) { - relatedTasks = new ArrayList<>(); - for (String taskId : getParams().message().referenceTaskIds()) { - Task task = taskStore.get(taskId); - if (task != null) { - relatedTasks.add(task); - } - } - } - - super.setRelatedTasks(relatedTasks); - return super.build(); - } -} diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/package-info.java b/server-common/src/main/java/io/a2a/server/agentexecution/package-info.java deleted file mode 100644 index 3fc934a52..000000000 --- a/server-common/src/main/java/io/a2a/server/agentexecution/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.agentexecution; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/auth/UnauthenticatedUser.java b/server-common/src/main/java/io/a2a/server/auth/UnauthenticatedUser.java deleted file mode 100644 index 9988ebbcf..000000000 --- a/server-common/src/main/java/io/a2a/server/auth/UnauthenticatedUser.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.server.auth; - -public class UnauthenticatedUser implements User { - - public static UnauthenticatedUser INSTANCE = new UnauthenticatedUser(); - - private UnauthenticatedUser() { - } - - @Override - public boolean isAuthenticated() { - return false; - } - - @Override - public String getUsername() { - return ""; - } -} diff --git a/server-common/src/main/java/io/a2a/server/auth/User.java b/server-common/src/main/java/io/a2a/server/auth/User.java deleted file mode 100644 index f41e98444..000000000 --- a/server-common/src/main/java/io/a2a/server/auth/User.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.a2a.server.auth; - -public interface User { - boolean isAuthenticated(); - String getUsername(); -} diff --git a/server-common/src/main/java/io/a2a/server/auth/package-info.java b/server-common/src/main/java/io/a2a/server/auth/package-info.java deleted file mode 100644 index 524d98fac..000000000 --- a/server-common/src/main/java/io/a2a/server/auth/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.auth; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/config/A2AConfigProvider.java b/server-common/src/main/java/io/a2a/server/config/A2AConfigProvider.java deleted file mode 100644 index ccd442e1c..000000000 --- a/server-common/src/main/java/io/a2a/server/config/A2AConfigProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.a2a.server.config; - -import java.util.Optional; - -/** - * Configuration provider interface for A2A SDK configuration values. - *

- * Implementations can obtain configuration from various sources: - *

    - *
  • {@link DefaultValuesConfigProvider} - Loads from META-INF/a2a-defaults.properties on classpath
  • - *
  • MicroProfileConfigProvider - Delegates to MicroProfile Config (reference implementations)
  • - *
  • Custom implementations - Can integrate with any configuration system
  • - *
- *

- * All configuration values are returned as strings. Consumers are responsible for type conversion. - */ -public interface A2AConfigProvider { - - /** - * Get a required configuration value. - * - * @param name the configuration property name - * @return the configuration value - * @throws IllegalArgumentException if the configuration value is not found - */ - String getValue(String name); - - /** - * Get an optional configuration value. - * - * @param name the configuration property name - * @return an Optional containing the value if present, empty otherwise - */ - Optional getOptionalValue(String name); -} diff --git a/server-common/src/main/java/io/a2a/server/config/DefaultValuesConfigProvider.java b/server-common/src/main/java/io/a2a/server/config/DefaultValuesConfigProvider.java deleted file mode 100644 index f2375ae57..000000000 --- a/server-common/src/main/java/io/a2a/server/config/DefaultValuesConfigProvider.java +++ /dev/null @@ -1,96 +0,0 @@ -package io.a2a.server.config; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Default configuration provider that loads values from {@code META-INF/a2a-defaults.properties} - * files on the classpath. - *

- * Each module (server-common, extras, etc.) can contribute a {@code META-INF/a2a-defaults.properties} - * file with default configuration values. All files are discovered and merged at startup. - *

- * If duplicate keys are found across different properties files, initialization will fail with - * an exception to prevent ambiguous configuration. - */ -@ApplicationScoped -public class DefaultValuesConfigProvider implements A2AConfigProvider { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultValuesConfigProvider.class); - private static final String DEFAULTS_RESOURCE = "META-INF/a2a-defaults.properties"; - - private final Map defaults = new HashMap<>(); - - @PostConstruct - void init() { - loadDefaultsFromClasspath(); - } - - private void loadDefaultsFromClasspath() { - try { - Enumeration resources = Thread.currentThread() - .getContextClassLoader() - .getResources(DEFAULTS_RESOURCE); - - Map sourceTracker = new HashMap<>(); // Track which file each key came from - - while (resources.hasMoreElements()) { - URL url = resources.nextElement(); - LOGGER.debug("Loading A2A defaults from: {}", url); - - Properties props = new Properties(); - try (InputStream is = url.openStream()) { - props.load(is); - - // Check for duplicates and merge - for (String key : props.stringPropertyNames()) { - String value = props.getProperty(key); - String existingSource = sourceTracker.get(key); - - if (existingSource != null) { - throw new IllegalStateException(String.format( - "Duplicate configuration key '%s' found in multiple a2a-defaults.properties files: %s and %s", - key, existingSource, url)); - } - - defaults.put(key, value); - sourceTracker.put(key, url.toString()); - LOGGER.trace("Loaded default: {} = {}", key, value); - } - } - } - - LOGGER.info("Loaded {} A2A default configuration values from {} resource(s)", - defaults.size(), sourceTracker.values().stream().distinct().count()); - - } catch (IOException e) { - throw new RuntimeException("Failed to load A2A default configuration from classpath", e); - } - } - - @Override - public String getValue(String name) { - String value = defaults.get(name); - if (value == null) { - throw new IllegalArgumentException("No default configuration value found for: " + name); - } - return value; - } - - @Override - public Optional getOptionalValue(String name) { - return Optional.ofNullable(defaults.get(name)); - } -} diff --git a/server-common/src/main/java/io/a2a/server/config/package-info.java b/server-common/src/main/java/io/a2a/server/config/package-info.java deleted file mode 100644 index 335bf450b..000000000 --- a/server-common/src/main/java/io/a2a/server/config/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.config; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java b/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java deleted file mode 100644 index 2ccf3fb60..000000000 --- a/server-common/src/main/java/io/a2a/server/events/EnhancedRunnable.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.a2a.server.events; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.jspecify.annotations.Nullable; - -public abstract class EnhancedRunnable implements Runnable { - private volatile @Nullable Throwable error; - private final List doneCallbacks = new CopyOnWriteArrayList<>(); - private final AtomicBoolean started = new AtomicBoolean(false); - - public @Nullable Throwable getError() { - return error; - } - - public void setError(Throwable error) { - this.error = error; - } - - public void addDoneCallback(DoneCallback doneCallback) { - if (started.get()) { - throw new IllegalStateException( - "Cannot add callback after runnable has started execution. " + - "Callbacks must be registered before CompletableFuture.runAsync() is called."); - } - doneCallbacks.add(doneCallback); - } - - /** - * Marks this runnable as started, preventing further callback additions. - * This should be called immediately before submitting to CompletableFuture.runAsync(). - */ - public void markStarted() { - started.set(true); - } - - public void invokeDoneCallbacks() { - for (DoneCallback doneCallback : doneCallbacks) { - doneCallback.done(this); - } - } - - public interface DoneCallback { - void done(EnhancedRunnable agentRunnable); - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/EventConsumer.java b/server-common/src/main/java/io/a2a/server/events/EventConsumer.java deleted file mode 100644 index 6fdfe8ea4..000000000 --- a/server-common/src/main/java/io/a2a/server/events/EventConsumer.java +++ /dev/null @@ -1,238 +0,0 @@ -package io.a2a.server.events; - -import java.util.concurrent.Flow; - -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import mutiny.zero.BackpressureStrategy; -import mutiny.zero.TubeConfiguration; -import mutiny.zero.ZeroPublisher; -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EventConsumer { - private static final Logger LOGGER = LoggerFactory.getLogger(EventConsumer.class); - private final EventQueue queue; - private volatile @Nullable Throwable error; - private volatile boolean cancelled = false; - private volatile boolean agentCompleted = false; - private volatile int pollTimeoutsAfterAgentCompleted = 0; - - private static final String ERROR_MSG = "Agent did not return any response"; - private static final int NO_WAIT = -1; - private static final int QUEUE_WAIT_MILLISECONDS = 500; - // In replicated scenarios, events can arrive hundreds of milliseconds after local agent completes - // Grace period allows Kafka replication to deliver late-arriving events - // 3 timeouts * 500ms = 1500ms grace period for replication delays - private static final int MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED = 3; - - public EventConsumer(EventQueue queue) { - this.queue = queue; - LOGGER.debug("EventConsumer created with queue {}", System.identityHashCode(queue)); - } - - public Event consumeOne() throws A2AServerException, EventQueueClosedException { - EventQueueItem item = queue.dequeueEventItem(NO_WAIT); - if (item == null) { - throw new A2AServerException(ERROR_MSG, new InternalError(ERROR_MSG)); - } - return item.getEvent(); - } - - public Flow.Publisher consumeAll() { - TubeConfiguration conf = new TubeConfiguration() - .withBackpressureStrategy(BackpressureStrategy.BUFFER) - .withBufferSize(256); - return ZeroPublisher.create(conf, tube -> { - boolean completed = false; - try { - while (true) { - // Check if cancelled by client disconnect - if (cancelled) { - LOGGER.debug("EventConsumer detected cancellation, exiting polling loop for queue {}", System.identityHashCode(queue)); - completed = true; - tube.complete(); - return; - } - - if (error != null) { - completed = true; - tube.fail(error); - return; - } - // We use a timeout when waiting for an event from the queue. - // This is required because it allows the loop to check if - // `self._exception` has been set by the `agent_task_callback`. - // Without the timeout, loop might hang indefinitely if no events are - // enqueued by the agent and the agent simply threw an exception - - // TODO the callback mentioned above seems unused in the Python 0.2.1 tag - EventQueueItem item; - Event event; - try { - LOGGER.debug("EventConsumer polling queue {} (error={}, agentCompleted={})", - System.identityHashCode(queue), error, agentCompleted); - item = queue.dequeueEventItem(QUEUE_WAIT_MILLISECONDS); - if (item == null) { - int queueSize = queue.size(); - LOGGER.debug("EventConsumer poll timeout (null item), agentCompleted={}, queue.size()={}, timeoutCount={}", - agentCompleted, queueSize, pollTimeoutsAfterAgentCompleted); - // If agent completed, a poll timeout means no more events are coming - // MainEventBusProcessor has 500ms to distribute events from MainEventBus - // If we timeout with agentCompleted=true, all events have been distributed - // - // IMPORTANT: In replicated scenarios, remote events may arrive AFTER local agent completes! - // Use grace period to allow for Kafka replication delays (can be 400-500ms) - if (agentCompleted && queueSize == 0) { - pollTimeoutsAfterAgentCompleted++; - if (pollTimeoutsAfterAgentCompleted >= MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED) { - LOGGER.debug("Agent completed with {} consecutive poll timeouts and empty queue, closing for graceful completion (queue={})", - pollTimeoutsAfterAgentCompleted, System.identityHashCode(queue)); - queue.close(); - completed = true; - tube.complete(); - return; - } else { - LOGGER.debug("Agent completed but grace period active ({}/{} timeouts), continuing to poll (queue={})", - pollTimeoutsAfterAgentCompleted, MAX_POLL_TIMEOUTS_AFTER_AGENT_COMPLETED, System.identityHashCode(queue)); - } - } else if (agentCompleted && queueSize > 0) { - LOGGER.debug("Agent completed but queue has {} pending events, resetting timeout counter and continuing to poll (queue={})", - queueSize, System.identityHashCode(queue)); - pollTimeoutsAfterAgentCompleted = 0; // Reset counter when events arrive - } - continue; - } - // Event received - reset timeout counter - pollTimeoutsAfterAgentCompleted = 0; - event = item.getEvent(); - LOGGER.debug("EventConsumer received event: {} (queue={})", - event.getClass().getSimpleName(), System.identityHashCode(queue)); - - // Defensive logging for error handling - if (event instanceof Throwable thr) { - LOGGER.debug("EventConsumer detected Throwable event: {} - triggering tube.fail()", - thr.getClass().getSimpleName()); - tube.fail(thr); - return; - } - - // Check for QueueClosedEvent BEFORE sending to avoid delivering it to subscribers - boolean isFinalEvent = false; - if (event instanceof TaskStatusUpdateEvent tue && tue.isFinal()) { - isFinalEvent = true; - } else if (event instanceof Message) { - isFinalEvent = true; - } else if (event instanceof Task task) { - isFinalEvent = isStreamTerminatingTask(task); - } else if (event instanceof QueueClosedEvent) { - // Poison pill event - signals queue closure from remote node - // Do NOT send to subscribers - just close the queue - LOGGER.debug("Received QueueClosedEvent for task {}, treating as final event", - ((QueueClosedEvent) event).getTaskId()); - isFinalEvent = true; - } else if (event instanceof A2AError) { - // A2AError events are terminal - they trigger automatic FAILED state transition - LOGGER.debug("Received A2AError event, treating as final event"); - isFinalEvent = true; - } - - // Only send event if it's not a QueueClosedEvent - // QueueClosedEvent is an internal coordination event used for replication - // and should not be exposed to API consumers - boolean isFinalSent = false; - if (!(event instanceof QueueClosedEvent)) { - tube.send(item); - isFinalSent = isFinalEvent; - } - - if (isFinalEvent) { - LOGGER.debug("Final or interrupted event detected, closing queue and breaking loop for queue {}", System.identityHashCode(queue)); - queue.close(); - LOGGER.debug("Queue closed, breaking loop for queue {}", System.identityHashCode(queue)); - - // CRITICAL: Allow tube buffer to flush before calling tube.complete() - // tube.send() buffers events asynchronously. If we call tube.complete() immediately, - // the stream-end signal can reach the client BEFORE the buffered final event, - // causing the client to close the connection and never receive the final event. - // This is especially important in replicated scenarios where events arrive via Kafka - // and timing is less deterministic. A small delay ensures the buffer flushes. - if (isFinalSent) { - try { - Thread.sleep(50); // 50ms to allow SSE buffer flush - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - break; - } - } catch (EventQueueClosedException e) { - completed = true; - tube.complete(); - return; - } catch (Throwable t) { - tube.fail(t); - return; - } - } - } finally { - if (!completed) { - LOGGER.debug("EventConsumer finally block: calling tube.complete() for queue {}", System.identityHashCode(queue)); - tube.complete(); - LOGGER.debug("EventConsumer finally block: tube.complete() returned for queue {}", System.identityHashCode(queue)); - } else { - LOGGER.debug("EventConsumer finally block: completed=true, skipping tube.complete() for queue {}", System.identityHashCode(queue)); - } - } - }); - } - - /** - * Determines if a task is in a state for terminating the stream. - *

A task is terminating if:

- *
    - *
  • Its state is final (e.g., completed, canceled, rejected, failed), OR
  • - *
  • Its state is interrupted (e.g., input-required)
  • - *
- * @param task the task to check - * @return true if the task has a final state or an interrupted state, false otherwise - */ - private boolean isStreamTerminatingTask(Task task) { - TaskState state = task.status().state(); - return state.isFinal() || state == TaskState.TASK_STATE_INPUT_REQUIRED; - } - - public EnhancedRunnable.DoneCallback createAgentRunnableDoneCallback() { - return agentRunnable -> { - LOGGER.debug("EventConsumer: Agent done callback invoked (hasError={}, queue={})", - agentRunnable.getError() != null, System.identityHashCode(queue)); - if (agentRunnable.getError() != null) { - error = agentRunnable.getError(); - LOGGER.debug("EventConsumer: Set error field from agent callback"); - } else { - agentCompleted = true; - LOGGER.debug("EventConsumer: Agent completed successfully, set agentCompleted=true, will close queue after draining"); - } - }; - } - - public void cancel() { - // Set cancellation flag to stop polling loop - // Called when client disconnects without completing stream - LOGGER.debug("EventConsumer cancelled (client disconnect), stopping polling for queue {}", System.identityHashCode(queue)); - cancelled = true; - } - - public void close() { - // Close the queue to stop the polling loop in consumeAll() - // This will cause EventQueueClosedException and exit the while(true) loop - LOGGER.debug("EventConsumer closing queue {}", System.identityHashCode(queue)); - queue.close(); - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/EventEnqueueHook.java b/server-common/src/main/java/io/a2a/server/events/EventEnqueueHook.java deleted file mode 100644 index e61284917..000000000 --- a/server-common/src/main/java/io/a2a/server/events/EventEnqueueHook.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.a2a.server.events; - -/** - * Hook interface for event queue enqueue operations. - * Implementations can be notified when items are enqueued to the event queue, - * allowing for custom behavior such as event replication or logging. - */ -public interface EventEnqueueHook { - /** - * Called when an item is enqueued to the event queue. - * - * @param item the event queue item being enqueued - */ - void onEnqueue(EventQueueItem item); -} \ No newline at end of file diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueue.java b/server-common/src/main/java/io/a2a/server/events/EventQueue.java deleted file mode 100644 index 53ae22da4..000000000 --- a/server-common/src/main/java/io/a2a/server/events/EventQueue.java +++ /dev/null @@ -1,813 +0,0 @@ -package io.a2a.server.events; - -import java.util.List; -import java.util.Objects; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import io.a2a.server.tasks.TaskStateProvider; -import io.a2a.spec.Event; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Abstract base class for event queues that manage task event streaming. - *

- * An EventQueue provides a thread-safe mechanism for enqueueing and dequeueing events - * related to task execution. It supports backpressure through semaphore-based throttling - * and hierarchical queue structures via MainQueue and ChildQueue implementations. - *

- *

- * Use {@link #builder(MainEventBus)} to create configured instances or extend MainQueue/ChildQueue directly. - *

- */ -public abstract class EventQueue implements AutoCloseable { - - private static final Logger LOGGER = LoggerFactory.getLogger(EventQueue.class); - - /** - * Default maximum queue size for event queues. - */ - public static final int DEFAULT_QUEUE_SIZE = 1000; - - private final int queueSize; - private volatile boolean closed = false; - - /** - * Creates an EventQueue with the default queue size. - */ - protected EventQueue() { - this(DEFAULT_QUEUE_SIZE); - } - - /** - * Creates an EventQueue with the specified queue size. - * - * @param queueSize the maximum number of events that can be queued - * @throws IllegalArgumentException if queueSize is less than or equal to 0 - */ - protected EventQueue(int queueSize) { - if (queueSize <= 0) { - throw new IllegalArgumentException("Queue size must be greater than 0"); - } - this.queueSize = queueSize; - LOGGER.trace("Creating {} with queue size: {}", this, queueSize); - } - - /** - * Creates an EventQueue as a child of the specified parent queue. - * - * @param parent the parent event queue - */ - protected EventQueue(EventQueue parent) { - this(DEFAULT_QUEUE_SIZE); - LOGGER.trace("Creating {}, parent: {}", this, parent); - } - - static EventQueueBuilder builder(MainEventBus mainEventBus) { - return new EventQueueBuilder().mainEventBus(mainEventBus); - } - - /** - * Builder for creating configured EventQueue instances. - *

- * Supports configuration of queue size, enqueue hooks, task association, - * close callbacks, and task state providers. - *

- */ - public static class EventQueueBuilder { - private int queueSize = DEFAULT_QUEUE_SIZE; - private @Nullable EventEnqueueHook hook; - private @Nullable String taskId; - private List onCloseCallbacks = new java.util.ArrayList<>(); - private @Nullable TaskStateProvider taskStateProvider; - private @Nullable MainEventBus mainEventBus; - - /** - * Sets the maximum queue size. - * - * @param queueSize the maximum number of events that can be queued - * @return this builder - */ - public EventQueueBuilder queueSize(int queueSize) { - this.queueSize = queueSize; - return this; - } - - /** - * Sets the enqueue hook for event replication or logging. - * - * @param hook the hook to be invoked when items are enqueued - * @return this builder - */ - public EventQueueBuilder hook(EventEnqueueHook hook) { - this.hook = hook; - return this; - } - - /** - * Associates this queue with a specific task ID. - * - * @param taskId the task identifier - * @return this builder - */ - public EventQueueBuilder taskId(String taskId) { - this.taskId = taskId; - return this; - } - - /** - * Adds a callback to be executed when the queue is closed. - * - * @param onCloseCallback the callback to execute on close - * @return this builder - */ - public EventQueueBuilder addOnCloseCallback(Runnable onCloseCallback) { - if (onCloseCallback != null) { - this.onCloseCallbacks.add(onCloseCallback); - } - return this; - } - - /** - * Sets the task state provider for tracking task finalization. - * - * @param taskStateProvider the task state provider - * @return this builder - */ - public EventQueueBuilder taskStateProvider(TaskStateProvider taskStateProvider) { - this.taskStateProvider = taskStateProvider; - return this; - } - - /** - * Sets the main event bus - * - * @param mainEventBus the main event bus - * @return this builder - */ - public EventQueueBuilder mainEventBus(MainEventBus mainEventBus) { - this.mainEventBus = mainEventBus; - return this; - } - - /** - * Builds and returns the configured EventQueue. - * - * @return a new MainQueue instance - */ - public EventQueue build() { - // MainEventBus is REQUIRED - enforce single architectural path - if (mainEventBus == null) { - throw new IllegalStateException("MainEventBus is required for EventQueue creation"); - } - if (taskId == null) { - throw new IllegalStateException("taskId is required for EventQueue creation"); - } - return new MainQueue(queueSize, hook, taskId, onCloseCallbacks, taskStateProvider, mainEventBus); - } - } - - /** - * Returns the configured queue size. - * - * @return the maximum number of events that can be queued - */ - public int getQueueSize() { - return queueSize; - } - - /** - * Waits for the queue poller to start consuming events. - * This method blocks until signaled by {@link #signalQueuePollerStarted()}. - * - * @throws InterruptedException if the thread is interrupted while waiting - */ - public abstract void awaitQueuePollerStart() throws InterruptedException ; - - /** - * Signals that the queue poller has started consuming events. - * This unblocks any threads waiting in {@link #awaitQueuePollerStart()}. - */ - public abstract void signalQueuePollerStarted(); - - /** - * Enqueues an event for processing. - * - * @param event the event to enqueue - */ - public void enqueueEvent(Event event) { - enqueueItem(new LocalEventQueueItem(event)); - } - - /** - * Enqueues an event queue item for processing. - *

- * This method will block if the queue is full, waiting to acquire a semaphore permit. - * If the queue is closed, the event will not be enqueued and a warning will be logged. - *

- * - * @param item the event queue item to enqueue - * @throws RuntimeException if interrupted while waiting to acquire the semaphore - */ - public abstract void enqueueItem(EventQueueItem item); - - /** - * Enqueues an event directly to this specific queue only, bypassing the MainEventBus. - *

- * This method is used for enqueuing already-persisted events (e.g., current task state - * on subscribe) that should only be sent to this specific subscriber, not distributed - * to all children or sent through MainEventBusProcessor. - *

- *

- * Default implementation throws UnsupportedOperationException. Only ChildQueue supports this. - *

- * - * @param item the event queue item to enqueue directly - * @throws UnsupportedOperationException if called on MainQueue or other queue types - */ - public void enqueueLocalOnly(EventQueueItem item) { - throw new UnsupportedOperationException( - "enqueueLocalOnly is only supported on ChildQueue for subscribe scenarios"); - } - - /** - * Enqueues an event directly to this specific queue only, bypassing the MainEventBus. - *

- * Convenience method that wraps the event in a LocalEventQueueItem before calling - * {@link #enqueueLocalOnly(EventQueueItem)}. - *

- * - * @param event the event to enqueue directly - * @throws UnsupportedOperationException if called on MainQueue or other queue types - */ - public void enqueueEventLocalOnly(Event event) { - enqueueLocalOnly(new LocalEventQueueItem(event)); - } - - /** - * Creates a child queue that shares events with this queue. - *

- * For MainQueue: creates a ChildQueue that receives all events enqueued to the parent. - * For ChildQueue: throws IllegalStateException (only MainQueue can be tapped). - *

- * - * @return a new ChildQueue instance - * @throws IllegalStateException if called on a ChildQueue - */ - public abstract EventQueue tap(); - - /** - * Dequeues an EventQueueItem from the queue. - *

- * This method returns the full EventQueueItem wrapper, allowing callers to check - * metadata like whether the event is replicated via {@link EventQueueItem#isReplicated()}. - *

- *

- * Note: MainQueue does not support dequeue operations - only ChildQueues can be consumed. - *

- * - * @param waitMilliSeconds the maximum time to wait in milliseconds - * @return the EventQueueItem, or null if timeout occurs - * @throws EventQueueClosedException if the queue is closed and empty - * @throws UnsupportedOperationException if called on MainQueue - */ - @Nullable - public abstract EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException; - - /** - * Placeholder method for task completion notification. - * Currently not used as BlockingQueue.poll()/take() automatically remove events. - */ - public void taskDone() { - // TODO Not sure if needed yet. BlockingQueue.poll()/.take() remove the events. - } - - /** - * Returns the current size of the queue. - *

- * For MainQueue: returns the number of events in-flight (in MainEventBus queue + currently being processed). - * This reflects actual capacity usage tracked by the semaphore. - * For ChildQueue: returns the size of the local consumption queue. - *

- * - * @return the number of events currently in the queue - */ - public abstract int size(); - - /** - * Closes this event queue gracefully, allowing pending events to be consumed. - */ - public abstract void close(); - - /** - * Closes this event queue with control over immediate shutdown. - * - * @param immediate if true, clears all pending events immediately; if false, allows graceful drain - */ - public abstract void close(boolean immediate); - - /** - * Close this queue with control over parent notification (ChildQueue only). - * - * @param immediate If true, clear all pending events immediately - * @param notifyParent If true, notify parent (standard behavior). If false, close this queue - * without decrementing parent's reference count (used for non-blocking - * non-final tasks to keep MainQueue alive for resubscription) - * @throws UnsupportedOperationException if called on MainQueue - */ - public abstract void close(boolean immediate, boolean notifyParent); - - /** - * Checks if this queue has been closed. - * - * @return true if the queue is closed, false otherwise - */ - public boolean isClosed() { - return closed; - } - - /** - * Internal method to close the queue gracefully. - * Delegates to {@link #doClose(boolean)} with immediate=false. - */ - protected void doClose() { - doClose(false); - } - - /** - * Internal method to close the queue with control over immediate shutdown. - * - * @param immediate if true, clears all pending events immediately; if false, allows graceful drain - */ - protected void doClose(boolean immediate) { - synchronized (this) { - if (closed) { - return; - } - LOGGER.debug("Closing {} (immediate={})", this, immediate); - closed = true; - } - // Subclasses handle immediate close logic (e.g., ChildQueue clears its local queue) - } - - static class MainQueue extends EventQueue { - private final List children = new CopyOnWriteArrayList<>(); - protected final Semaphore semaphore; - private final CountDownLatch pollingStartedLatch = new CountDownLatch(1); - private final AtomicBoolean pollingStarted = new AtomicBoolean(false); - private final @Nullable EventEnqueueHook enqueueHook; - private final String taskId; - private final List onCloseCallbacks; - private final @Nullable TaskStateProvider taskStateProvider; - private final MainEventBus mainEventBus; - - MainQueue(int queueSize, - @Nullable EventEnqueueHook hook, - String taskId, - List onCloseCallbacks, - @Nullable TaskStateProvider taskStateProvider, - @Nullable MainEventBus mainEventBus) { - super(queueSize); - this.semaphore = new Semaphore(queueSize, true); - this.enqueueHook = hook; - this.taskId = taskId; - this.onCloseCallbacks = List.copyOf(onCloseCallbacks); // Defensive copy - this.taskStateProvider = taskStateProvider; - this.mainEventBus = Objects.requireNonNull(mainEventBus, "MainEventBus is required"); - LOGGER.debug("Created MainQueue for task {} with {} onClose callbacks, TaskStateProvider: {}, MainEventBus configured", - taskId, onCloseCallbacks.size(), taskStateProvider != null); - } - - - public EventQueue tap() { - ChildQueue child = new ChildQueue(this); - children.add(child); - return child; - } - - /** - * Returns the current number of child queues. - * Useful for debugging and logging event distribution. - */ - public int getChildCount() { - return children.size(); - } - - /** - * Returns the enqueue hook for replication (package-protected for MainEventBusProcessor). - */ - @Nullable EventEnqueueHook getEnqueueHook() { - return enqueueHook; - } - - @Override - public EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException { - throw new UnsupportedOperationException("MainQueue cannot be consumed directly - use tap() to create a ChildQueue for consumption"); - } - - @Override - public int size() { - // Return total in-flight events (in MainEventBus + being processed) - // This aligns with semaphore's capacity tracking - return getQueueSize() - semaphore.availablePermits(); - } - - @Override - public void enqueueItem(EventQueueItem item) { - // MainQueue must accept events even when closed to support: - // 1. Late-arriving replicated events for non-finalized tasks - // 2. Events enqueued during onClose callbacks (before super.doClose()) - // 3. QueueClosedEvent termination for remote subscribers - // - // We bypass the parent's closed check and enqueue directly - Event event = item.getEvent(); - - // Validate event taskId matches queue taskId - validateEventIds(event); - - // Check if this is a final event BEFORE submitting to MainEventBus - // If it is, notify all children to expect it (so they wait for MainEventBusProcessor) - if (isFinalEvent(event)) { - LOGGER.debug("Final event detected, notifying {} children to expect it", children.size()); - for (ChildQueue child : children) { - child.expectFinalEvent(); - } - } - - // Acquire semaphore for backpressure - try { - semaphore.acquire(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Unable to acquire the semaphore to enqueue the event", e); - } - - LOGGER.debug("Enqueued event {} {}", event instanceof Throwable ? event.toString() : event, this); - - // Submit to MainEventBus for centralized persistence + distribution - // MainEventBus is guaranteed non-null by constructor requirement - // Note: Replication now happens in MainEventBusProcessor AFTER persistence - - // Submit event to MainEventBus with our taskId - mainEventBus.submit(taskId, this, item); - } - - /** - * Validates that events with taskId fields match this queue's taskId. - * - *

Validation Rules: - *

    - *
  • Task, TaskStatusUpdateEvent, TaskArtifactUpdateEvent: MUST match queue taskId
  • - *
  • Message: taskId is OPTIONAL, not validated (can exist without tasks)
  • - *
  • Other events: no validation
  • - *
  • Null queue taskId: skip validation (initialization phase)
  • - *
- * - * @param event the event to validate - * @throws IllegalArgumentException if event has mismatched taskId - */ - private void validateEventIds(Event event) { - if (taskId == null) { - return; // Allow any event during initialization - } - - String eventTaskId = null; - String eventType = null; - - if (event instanceof Task task) { - eventTaskId = task.id(); - eventType = "Task"; - } else if (event instanceof TaskStatusUpdateEvent statusEvent) { - eventTaskId = statusEvent.taskId(); - eventType = "TaskStatusUpdateEvent"; - } else if (event instanceof TaskArtifactUpdateEvent artifactEvent) { - eventTaskId = artifactEvent.taskId(); - eventType = "TaskArtifactUpdateEvent"; - } - // Note: Message.taskId is NOT validated - messages can exist independently - - if (eventTaskId != null && !eventTaskId.equals(taskId)) { - throw new IllegalArgumentException( - String.format("Event taskId mismatch: queue=%s, event=%s, eventType=%s", - taskId, eventTaskId, eventType)); - } - } - - /** - * Checks if an event represents a final task state. - */ - private boolean isFinalEvent(Event event) { - if (event instanceof Task task) { - return task.status() != null && task.status().state() != null - && task.status().state().isFinal(); - } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { - return statusUpdate.isFinal(); - } - return false; - } - - @Override - public void awaitQueuePollerStart() throws InterruptedException { - LOGGER.debug("Waiting for queue poller to start on {}", this); - pollingStartedLatch.await(10, TimeUnit.SECONDS); - LOGGER.debug("Queue poller started on {}", this); - } - - @Override - public void signalQueuePollerStarted() { - if (pollingStarted.get()) { - return; - } - LOGGER.debug("Signalling that queue polling started {}", this); - pollingStartedLatch.countDown(); - pollingStarted.set(true); - } - - void childClosing(ChildQueue child, boolean immediate) { - children.remove(child); // Remove the closing child - - // If there are still children, keep queue open - if (!children.isEmpty()) { - LOGGER.debug("MainQueue staying open: {} children remaining", children.size()); - return; - } - - // No children left - check if task is finalized before closing - // IMPORTANT: This check must happen BEFORE the immediate flag check - // to prevent closing queues for non-final tasks (fire-and-forget, resubscription support) - if (taskStateProvider != null && taskId != null) { - boolean isFinalized = taskStateProvider.isTaskFinalized(taskId); - if (!isFinalized) { - LOGGER.debug("MainQueue for task {} has no children, but task is not finalized - keeping queue open for potential resubscriptions", taskId); - return; // Don't close - keep queue open for fire-and-forget or late subscribes - } - LOGGER.debug("MainQueue for task {} has no children and task is finalized - closing queue", taskId); - } else { - LOGGER.debug("MainQueue has no children and no TaskStateProvider - closing queue (legacy behavior)"); - } - - this.doClose(immediate); - } - - /** - * Distribute event to all ChildQueues. - * Called by MainEventBusProcessor after TaskStore persistence. - */ - void distributeToChildren(EventQueueItem item) { - int childCount = children.size(); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MainQueue[{}]: Distributing event {} to {} children", - taskId, item.getEvent().getClass().getSimpleName(), childCount); - } - children.forEach(child -> { - LOGGER.debug("MainQueue[{}]: Enqueueing event {} to child queue", - taskId, item.getEvent().getClass().getSimpleName()); - child.internalEnqueueItem(item); - }); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("MainQueue[{}]: Completed distribution of {} to {} children", - taskId, item.getEvent().getClass().getSimpleName(), childCount); - } - } - - /** - * Release the semaphore after event processing is complete. - * Called by MainEventBusProcessor in finally block to ensure release even on exceptions. - * Balances the acquire() in enqueueEvent() - protects MainEventBus throughput. - */ - void releaseSemaphore() { - semaphore.release(); - } - - /** - * Get the count of active child queues. - * Used for testing to verify reference counting mechanism. - * - * @return number of active child queues - */ - public int getActiveChildCount() { - return children.size(); - } - - @Override - protected void doClose(boolean immediate) { - // Invoke all callbacks BEFORE closing, so they can still enqueue events - if (!onCloseCallbacks.isEmpty()) { - LOGGER.debug("Invoking {} onClose callbacks for task {} BEFORE closing", onCloseCallbacks.size(), taskId); - for (Runnable callback : onCloseCallbacks) { - try { - callback.run(); - } catch (Exception e) { - LOGGER.error("Error in onClose callback for task {}", taskId, e); - } - } - } - // Now close the queue - super.doClose(immediate); - } - - @Override - public void close() { - close(false); - } - - @Override - public void close(boolean immediate) { - doClose(immediate); - if (immediate) { - // Force-close all remaining children - children.forEach(child -> child.doClose(immediate)); - } - children.clear(); - } - - @Override - public void close(boolean immediate, boolean notifyParent) { - throw new UnsupportedOperationException("MainQueue does not support notifyParent parameter - use close(boolean) instead"); - } - - String getTaskId() { - return taskId; - } - } - - static class ChildQueue extends EventQueue { - private final MainQueue parent; - private final BlockingQueue queue = new LinkedBlockingDeque<>(); - private volatile boolean immediateClose = false; - private volatile boolean awaitingFinalEvent = false; - - public ChildQueue(MainQueue parent) { - this.parent = parent; - } - - @Override - public void enqueueEvent(Event event) { - parent.enqueueEvent(event); - } - - @Override - public void enqueueItem(EventQueueItem item) { - // ChildQueue delegates writes to parent MainQueue - parent.enqueueItem(item); - } - - private void internalEnqueueItem(EventQueueItem item) { - // Internal method called by MainEventBusProcessor to add to local queue - // Note: Semaphore is managed by parent MainQueue (acquire/release), not ChildQueue - Event event = item.getEvent(); - // For graceful close: still accept events so they can be drained by EventConsumer - // For immediate close: reject events to stop distribution quickly - if (isClosed() && immediateClose) { - LOGGER.warn("ChildQueue is immediately closed. Event will not be enqueued. {} {}", this, event); - return; - } - if (!queue.offer(item)) { - LOGGER.warn("ChildQueue {} is full. Closing immediately.", this); - close(true); // immediate close - } else { - LOGGER.debug("Enqueued event {} {}", event instanceof Throwable ? event.toString() : event, this); - - // If we were awaiting a final event and this is it, clear the flag - if (awaitingFinalEvent && isFinalEvent(event)) { - awaitingFinalEvent = false; - LOGGER.debug("ChildQueue {} received awaited final event", System.identityHashCode(this)); - } - } - } - - /** - * Checks if an event represents a final task state. - */ - private boolean isFinalEvent(Event event) { - if (event instanceof Task task) { - return task.status() != null && task.status().state() != null - && task.status().state().isFinal(); - } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { - return statusUpdate.isFinal(); - } - return false; - } - - @Override - public void enqueueLocalOnly(EventQueueItem item) { - internalEnqueueItem(item); - } - - @Override - @Nullable - public EventQueueItem dequeueEventItem(int waitMilliSeconds) throws EventQueueClosedException { - // CRITICAL: Signal polling started BEFORE any early returns - // This ensures awaitQueuePollerStart() unblocks even if queue is already closed - signalQueuePollerStarted(); - - // For immediate close: exit immediately even if queue is not empty (race with MainEventBusProcessor) - // For graceful close: only exit when queue is empty (wait for all events to be consumed) - // BUT: if awaiting final event, keep polling even if closed and empty - if (isClosed() && (queue.isEmpty() || immediateClose) && !awaitingFinalEvent) { - LOGGER.debug("ChildQueue is closed{}, sending termination message. {} (queueSize={})", - immediateClose ? " (immediate)" : " and empty", - this, - queue.size()); - throw new EventQueueClosedException(); - } - if (waitMilliSeconds <= 0) { - EventQueueItem item = queue.poll(); - if (item != null) { - Event event = item.getEvent(); - LOGGER.debug("Dequeued event item (no wait) {} {}", this, event instanceof Throwable ? event.toString() : event); - } - return item; - } - try { - LOGGER.trace("Polling ChildQueue {} (wait={}ms)", System.identityHashCode(this), waitMilliSeconds); - EventQueueItem item = queue.poll(waitMilliSeconds, TimeUnit.MILLISECONDS); - if (item != null) { - Event event = item.getEvent(); - LOGGER.debug("Dequeued event item (waiting) {} {}", this, event instanceof Throwable ? event.toString() : event); - } else { - LOGGER.trace("Dequeue timeout (null) from ChildQueue {}", System.identityHashCode(this)); - } - return item; - } catch (InterruptedException e) { - LOGGER.debug("Interrupted dequeue (waiting) {}", this); - Thread.currentThread().interrupt(); - return null; - } - } - - @Override - public EventQueue tap() { - throw new IllegalStateException("Can only tap the main queue"); - } - - @Override - public int size() { - // Return size of local consumption queue - return queue.size(); - } - - @Override - public void awaitQueuePollerStart() throws InterruptedException { - parent.awaitQueuePollerStart(); - } - - @Override - public void signalQueuePollerStarted() { - parent.signalQueuePollerStarted(); - } - - @Override - protected void doClose(boolean immediate) { - super.doClose(immediate); // Sets closed flag - if (immediate) { - // Immediate close: clear pending events from local queue - this.immediateClose = true; - int clearedCount = queue.size(); - queue.clear(); - LOGGER.debug("Cleared {} events from ChildQueue for immediate close: {}", clearedCount, this); - } - // For graceful close, let the queue drain naturally through normal consumption - } - - /** - * Notifies this ChildQueue to expect a final event. - * Called by MainQueue when it enqueues a final event, BEFORE submitting to MainEventBus. - * This ensures the ChildQueue keeps polling until the final event arrives (after MainEventBusProcessor). - */ - void expectFinalEvent() { - awaitingFinalEvent = true; - LOGGER.debug("ChildQueue {} now awaiting final event", System.identityHashCode(this)); - } - - @Override - public void close() { - close(false); - } - - @Override - public void close(boolean immediate) { - close(immediate, true); - } - - @Override - public void close(boolean immediate, boolean notifyParent) { - this.doClose(immediate); // Close self first - if (notifyParent) { - parent.childClosing(this, immediate); // Notify parent - } else { - LOGGER.debug("Closing {} without notifying parent (keeping MainQueue alive)", this); - } - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueueClosedException.java b/server-common/src/main/java/io/a2a/server/events/EventQueueClosedException.java deleted file mode 100644 index 5fe80637d..000000000 --- a/server-common/src/main/java/io/a2a/server/events/EventQueueClosedException.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.a2a.server.events; - -/** - * Exception thrown when attempting to dequeue from a closed and empty event queue. - * This signals to consumers that no more events will be available from the queue. - */ -public class EventQueueClosedException extends Exception { -} diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueueFactory.java b/server-common/src/main/java/io/a2a/server/events/EventQueueFactory.java deleted file mode 100644 index 3f062e660..000000000 --- a/server-common/src/main/java/io/a2a/server/events/EventQueueFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.a2a.server.events; - -public interface EventQueueFactory { - /** - * Creates an EventQueueBuilder with the specified taskId context. - * This allows the factory to create queues with task-specific configuration. - * - * @param taskId the task ID for which the queue is being created - * @return an EventQueueBuilder configured for the specified task - */ - EventQueue.EventQueueBuilder builder(String taskId); -} \ No newline at end of file diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueueItem.java b/server-common/src/main/java/io/a2a/server/events/EventQueueItem.java deleted file mode 100644 index e2bfc8f3c..000000000 --- a/server-common/src/main/java/io/a2a/server/events/EventQueueItem.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.a2a.server.events; - -import io.a2a.spec.Event; - -/** - * Represents an item that can be enqueued/dequeued in an EventQueue. - *

- * This abstraction allows the queue to track whether events originated locally - * or were received from replication, enabling proper handling of the replication loop - * prevention mechanism. - *

- */ -public interface EventQueueItem { - - /** - * Gets the event contained in this queue item. - * - * @return the event - */ - Event getEvent(); - - /** - * Checks if this item represents a replicated event. - *

- * Replicated events are those received from other nodes in the cluster via - * the replication mechanism (e.g., Kafka). Local events are those enqueued - * directly by the local agent execution. - *

- *

- * This distinction is important to prevent replication loops - replicated events - * should not be re-replicated to other nodes. - *

- * - * @return true if this event was replicated from another node, false if it's a local event - */ - boolean isReplicated(); -} diff --git a/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java b/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java deleted file mode 100644 index 53a089e4c..000000000 --- a/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java +++ /dev/null @@ -1,205 +0,0 @@ -package io.a2a.server.events; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import io.a2a.server.tasks.TaskStateProvider; -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -public class InMemoryQueueManager implements QueueManager { - private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryQueueManager.class); - - private final ConcurrentMap queues = new ConcurrentHashMap<>(); - // Fields set by constructor injection cannot be final. We need a noargs constructor for - // Jakarta compatibility, and it seems that making fields set by constructor injection - // final, is not proxyable in all runtimes - private EventQueueFactory factory; - private TaskStateProvider taskStateProvider; - - /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. - */ - @SuppressWarnings("NullAway") - protected InMemoryQueueManager() { - // For CDI proxy creation - this.factory = null; - this.taskStateProvider = null; - } - - MainEventBus mainEventBus; - - @Inject - public InMemoryQueueManager(TaskStateProvider taskStateProvider, MainEventBus mainEventBus) { - this.mainEventBus = mainEventBus; - this.factory = new DefaultEventQueueFactory(); - this.taskStateProvider = taskStateProvider; - } - - // For testing/extensions with custom factory and MainEventBus - public InMemoryQueueManager(EventQueueFactory factory, TaskStateProvider taskStateProvider, MainEventBus mainEventBus) { - this.factory = factory; - this.taskStateProvider = taskStateProvider; - this.mainEventBus = mainEventBus; - } - - @Override - public void add(String taskId, EventQueue queue) { - EventQueue existing = queues.putIfAbsent(taskId, queue); - if (existing != null) { - throw new TaskQueueExistsException(); - } - } - - @Override - public @Nullable EventQueue get(String taskId) { - return queues.get(taskId); - } - - @Override - public @Nullable EventQueue tap(String taskId) { - EventQueue queue = queues.get(taskId); - return queue == null ? null : queue.tap(); - } - - @Override - public void close(String taskId) { - EventQueue existing = queues.remove(taskId); - if (existing == null) { - throw new NoTaskQueueException(); - } - // Close the queue to stop EventConsumer polling loop - LOGGER.debug("Closing queue {} for task {}", System.identityHashCode(existing), taskId); - existing.close(); - } - - @Override - public EventQueue createOrTap(String taskId) { - LOGGER.debug("createOrTap called for task {}, current map size: {}", taskId, queues.size()); - EventQueue existing = queues.get(taskId); - - // Lazy cleanup: only remove closed queues if task is finalized - // Don't remove queues for non-finalized tasks - they must stay for late-arriving events - if (existing != null && existing.isClosed()) { - boolean isFinalized = (taskStateProvider != null) && taskStateProvider.isTaskFinalized(taskId); - if (isFinalized) { - LOGGER.debug("Removing closed queue {} for finalized task {}", System.identityHashCode(existing), taskId); - queues.remove(taskId); - existing = null; - } else { - LOGGER.debug("Queue {} for task {} is closed but task not finalized - keeping for late-arriving events", - System.identityHashCode(existing), taskId); - // Don't remove or recreate - existing closed queue stays in map - // This is critical for replication where events may arrive after MainQueue closes - // The closed MainQueue can still receive enqueued events via enqueueEvent() - } - } - - EventQueue newQueue = null; - if (existing == null) { - // Use builder pattern for cleaner queue creation - newQueue = factory.builder(taskId).build(); - // Make sure an existing queue has not been added in the meantime - existing = queues.putIfAbsent(taskId, newQueue); - } - - EventQueue main = existing == null ? newQueue : existing; - if (main == null) { - throw new IllegalStateException("Failed to create or retrieve queue for task " + taskId); - } - EventQueue result = main.tap(); // Always return ChildQueue - - if (existing == null) { - LOGGER.debug("Created new MainQueue {} for task {}, returning ChildQueue {} (map size: {})", - System.identityHashCode(main), taskId, System.identityHashCode(result), queues.size()); - } else { - LOGGER.debug("Tapped existing MainQueue {} -> ChildQueue {} for task {}", - System.identityHashCode(main), System.identityHashCode(result), taskId); - } - return result; - } - - @Override - public void awaitQueuePollerStart(EventQueue eventQueue) throws InterruptedException { - eventQueue.awaitQueuePollerStart(); - } - - @Override - public EventQueue.EventQueueBuilder getEventQueueBuilder(String taskId) { - // Use the factory to ensure proper configuration (MainEventBus, callbacks, etc.) - return factory.builder(taskId); - } - - @Override - public int getActiveChildQueueCount(String taskId) { - EventQueue queue = queues.get(taskId); - if (queue == null || queue.isClosed()) { - return -1; // Queue doesn't exist or is closed - } - // Cast to MainQueue to access getActiveChildCount() - if (queue instanceof EventQueue.MainQueue mainQueue) { - return mainQueue.getActiveChildCount(); - } - // This should not happen in normal operation since we only store MainQueues - return -1; - } - - @Override - public EventQueue.EventQueueBuilder createBaseEventQueueBuilder(String taskId) { - return EventQueue.builder(mainEventBus) - .taskId(taskId) - .addOnCloseCallback(getCleanupCallback(taskId)) - .taskStateProvider(taskStateProvider); - } - - /** - * Get the cleanup callback that removes a queue from the map when it closes. - * This is exposed so that subclasses (like ReplicatedQueueManager) can reuse - * this cleanup logic while adding their own callbacks in the correct order. - *

- * The cleanup callback checks if the task is finalized before removing the queue. - * If the task is not finalized, the queue remains in the map to handle late-arriving events. - *

- * - * @param taskId the task ID for the queue - * @return a Runnable that removes the queue from the map if appropriate - */ - public Runnable getCleanupCallback(String taskId) { - return () -> { - LOGGER.debug("Queue close callback invoked for task {}", taskId); - - // Check if task is finalized before removing queue - boolean isFinalized = (taskStateProvider != null) && taskStateProvider.isTaskFinalized(taskId); - - if (!isFinalized) { - LOGGER.debug("Task {} is not finalized, keeping queue in map for late-arriving events", taskId); - return; // Don't remove from map - task is still active - } - - LOGGER.debug("Task {} is finalized, removing queue from map", taskId); - - EventQueue removed = queues.remove(taskId); - if (removed != null) { - LOGGER.debug("Removed closed queue for task {} from QueueManager (map size: {})", - taskId, queues.size()); - } else { - LOGGER.debug("Queue for task {} was already removed from map", taskId); - } - }; - } - - private class DefaultEventQueueFactory implements EventQueueFactory { - @Override - public EventQueue.EventQueueBuilder builder(String taskId) { - // Delegate to the base builder creation method - return createBaseEventQueueBuilder(taskId); - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/LocalEventQueueItem.java b/server-common/src/main/java/io/a2a/server/events/LocalEventQueueItem.java deleted file mode 100644 index 88c32024d..000000000 --- a/server-common/src/main/java/io/a2a/server/events/LocalEventQueueItem.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.a2a.server.events; - -import io.a2a.spec.Event; -import io.a2a.util.Assert; - -/** - * Represents a locally-generated event in the queue. - *

- * Local events are those enqueued directly by the agent executor on this node, - * as opposed to events received via replication from other nodes. - *

- */ -class LocalEventQueueItem implements EventQueueItem { - - private final Event event; - - LocalEventQueueItem(Event event) { - Assert.checkNotNullParam("event", event); - this.event = event; - } - - @Override - public Event getEvent() { - return event; - } - - @Override - public boolean isReplicated() { - return false; - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBus.java b/server-common/src/main/java/io/a2a/server/events/MainEventBus.java deleted file mode 100644 index 90080b1e2..000000000 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBus.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.a2a.server.events; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingDeque; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import jakarta.enterprise.context.ApplicationScoped; - -@ApplicationScoped -public class MainEventBus { - private static final Logger LOGGER = LoggerFactory.getLogger(MainEventBus.class); - private final BlockingQueue queue; - - public MainEventBus() { - this.queue = new LinkedBlockingDeque<>(); - } - - void submit(String taskId, EventQueue.MainQueue mainQueue, EventQueueItem item) { - try { - queue.put(new MainEventBusContext(taskId, mainQueue, item)); - LOGGER.debug("Submitted event for task {} to MainEventBus (queue size: {})", - taskId, queue.size()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Interrupted submitting to MainEventBus", e); - } - } - - MainEventBusContext take() throws InterruptedException { - LOGGER.debug("MainEventBus: Waiting to take event (current queue size: {})...", queue.size()); - MainEventBusContext context = queue.take(); - LOGGER.debug("MainEventBus: Took event for task {} (remaining queue size: {})", - context.taskId(), queue.size()); - return context; - } - - public int size() { - return queue.size(); - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java deleted file mode 100644 index 292a60f21..000000000 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusContext.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.a2a.server.events; - -import java.util.Objects; - -record MainEventBusContext(String taskId, EventQueue.MainQueue eventQueue, EventQueueItem eventQueueItem) { - MainEventBusContext { - Objects.requireNonNull(taskId, "taskId cannot be null"); - Objects.requireNonNull(eventQueue, "eventQueue cannot be null"); - Objects.requireNonNull(eventQueueItem, "eventQueueItem cannot be null"); - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java deleted file mode 100644 index 575078679..000000000 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessor.java +++ /dev/null @@ -1,395 +0,0 @@ -package io.a2a.server.events; - -import java.util.concurrent.CompletableFuture; - -import jakarta.annotation.Nullable; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.server.tasks.TaskManager; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Background processor for the MainEventBus. - *

- * This processor runs in a dedicated background thread, consuming events from the MainEventBus - * and performing two critical operations in order: - *

- *
    - *
  1. Update TaskStore with event data (persistence FIRST)
  2. - *
  3. Distribute event to ChildQueues (clients see it AFTER persistence)
  4. - *
- *

- * This architecture ensures clients never receive events before they're persisted, - * eliminating race conditions and enabling reliable event replay. - *

- *

- * Note: This bean is eagerly initialized by {@link MainEventBusProcessorInitializer} - * to ensure the background thread starts automatically when the application starts. - *

- */ -@ApplicationScoped -public class MainEventBusProcessor implements Runnable { - private static final Logger LOGGER = LoggerFactory.getLogger(MainEventBusProcessor.class); - - /** - * Callback for testing synchronization with async event processing. - * Default is NOOP to avoid null checks in production code. - * Tests can inject their own callback via setCallback(). - */ - private volatile MainEventBusProcessorCallback callback = MainEventBusProcessorCallback.NOOP; - - /** - * Optional executor for push notifications. - * If null, uses default ForkJoinPool (async). - * Tests can inject a synchronous executor to ensure deterministic ordering. - */ - private volatile @Nullable java.util.concurrent.Executor pushNotificationExecutor = null; - - private MainEventBus eventBus; - - private TaskStore taskStore; - - private PushNotificationSender pushSender; - - private QueueManager queueManager; - - private volatile boolean running = true; - private @Nullable Thread processorThread; - - /** - * No-arg constructor for CDI proxying. - * CDI requires this for @ApplicationScoped beans. - * Fields are initialized via the @Inject constructor. - */ - @SuppressWarnings("NullAway") - protected MainEventBusProcessor() { - } - - @Inject - public MainEventBusProcessor(MainEventBus eventBus, TaskStore taskStore, PushNotificationSender pushSender, QueueManager queueManager) { - this.eventBus = eventBus; - this.taskStore = taskStore; - this.pushSender = pushSender; - this.queueManager = queueManager; - } - - /** - * Set a callback for testing synchronization with async event processing. - *

- * This is primarily intended for tests that need to wait for event processing to complete. - * Pass null to reset to the default NOOP callback. - *

- * - * @param callback the callback to invoke during event processing, or null for NOOP - */ - public void setCallback(MainEventBusProcessorCallback callback) { - this.callback = callback != null ? callback : MainEventBusProcessorCallback.NOOP; - } - - /** - * Set a custom executor for push notifications (primarily for testing). - *

- * By default, push notifications are sent asynchronously using CompletableFuture.runAsync() - * with the default ForkJoinPool. For tests that need deterministic ordering of push - * notifications, inject a synchronous executor that runs tasks immediately on the calling thread. - *

- * Example synchronous executor for tests: - *
{@code
-     * Executor syncExecutor = Runnable::run;
-     * mainEventBusProcessor.setPushNotificationExecutor(syncExecutor);
-     * }
- * - * @param executor the executor to use for push notifications, or null to use default ForkJoinPool - */ - public void setPushNotificationExecutor(java.util.concurrent.Executor executor) { - this.pushNotificationExecutor = executor; - } - - @PostConstruct - void start() { - processorThread = new Thread(this, "MainEventBusProcessor"); - processorThread.setDaemon(true); // Allow JVM to exit even if this thread is running - processorThread.start(); - LOGGER.info("MainEventBusProcessor started"); - } - - /** - * No-op method to force CDI proxy resolution and ensure @PostConstruct has been called. - * Called by MainEventBusProcessorInitializer during application startup. - */ - public void ensureStarted() { - // Method intentionally empty - just forces proxy resolution - } - - @PreDestroy - void stop() { - LOGGER.info("MainEventBusProcessor stopping..."); - running = false; - if (processorThread != null) { - processorThread.interrupt(); - try { - long start = System.currentTimeMillis(); - processorThread.join(5000); // Wait up to 5 seconds - long elapsed = System.currentTimeMillis() - start; - LOGGER.info("MainEventBusProcessor thread stopped in {}ms", elapsed); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOGGER.warn("Interrupted while waiting for MainEventBusProcessor thread to stop"); - } - } - LOGGER.info("MainEventBusProcessor stopped"); - } - - @Override - public void run() { - LOGGER.info("MainEventBusProcessor processing loop started"); - while (running) { - try { - LOGGER.debug("MainEventBusProcessor: Waiting for event from MainEventBus..."); - MainEventBusContext context = eventBus.take(); - LOGGER.debug("MainEventBusProcessor: Retrieved event for task {} from MainEventBus", - context.taskId()); - processEvent(context); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOGGER.info("MainEventBusProcessor interrupted, shutting down"); - break; - } catch (Exception e) { - LOGGER.error("Error processing event from MainEventBus", e); - // Continue processing despite errors - } - } - LOGGER.info("MainEventBusProcessor processing loop ended"); - } - - private void processEvent(MainEventBusContext context) { - String taskId = context.taskId(); - Event event = context.eventQueueItem().getEvent(); - // MainEventBus.submit() guarantees this is always a MainQueue - EventQueue.MainQueue mainQueue = (EventQueue.MainQueue) context.eventQueue(); - - LOGGER.debug("MainEventBusProcessor: Processing event for task {}: {}", - taskId, event.getClass().getSimpleName()); - - Event eventToDistribute = null; - boolean isReplicated = context.eventQueueItem().isReplicated(); - try { - // Step 1: Update TaskStore FIRST (persistence before clients see it) - // If this throws, we distribute an error to ensure "persist before client visibility" - - try { - boolean isFinal = updateTaskStore(taskId, event, isReplicated); - - eventToDistribute = event; // Success - distribute original event - - // Trigger replication AFTER successful persistence - // SKIP replication if task is final - ReplicatedQueueManager handles this via TaskFinalizedEvent - // to ensure final Task is sent before poison pill (QueueClosedEvent) - if (!isFinal) { - EventEnqueueHook hook = mainQueue.getEnqueueHook(); - if (hook != null) { - LOGGER.debug("Triggering replication hook for task {} after successful persistence", taskId); - hook.onEnqueue(context.eventQueueItem()); - } - } else { - LOGGER.debug("Task {} is final - skipping replication hook (handled by ReplicatedQueueManager)", taskId); - } - } catch (InternalError e) { - // Persistence failed - create error event to distribute instead - LOGGER.error("Failed to persist event for task {}, distributing error to clients", taskId, e); - String errorMessage = "Failed to persist event: " + e.getMessage(); - eventToDistribute = e; - } catch (Exception e) { - LOGGER.error("Failed to persist event for task {}, distributing error to clients", taskId, e); - String errorMessage = "Failed to persist event: " + e.getMessage(); - eventToDistribute = new InternalError(errorMessage); - } - - // Step 2: Send push notification AFTER successful persistence (only from active node) - // Skip push notifications for replicated events to avoid duplicate notifications in multi-instance deployments - // Push notifications are sent for all StreamingEventKind events (Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent) - // per A2A spec section 4.3.3 - if (!isReplicated && event instanceof StreamingEventKind streamingEvent) { - // Send the streaming event directly - it will be wrapped in StreamResponse format by PushNotificationSender - sendPushNotification(taskId, streamingEvent); - } - - // Step 3: Then distribute to ChildQueues (clients see either event or error AFTER persistence attempt) - int childCount = mainQueue.getChildCount(); - LOGGER.debug("MainEventBusProcessor: Distributing {} to {} children for task {}", - eventToDistribute.getClass().getSimpleName(), childCount, taskId); - // Create new EventQueueItem with the event to distribute (original or error) - EventQueueItem itemToDistribute = new LocalEventQueueItem(eventToDistribute); - mainQueue.distributeToChildren(itemToDistribute); - LOGGER.debug("MainEventBusProcessor: Distributed {} to {} children for task {}", - eventToDistribute.getClass().getSimpleName(), childCount, taskId); - - LOGGER.debug("MainEventBusProcessor: Completed processing event for task {}", taskId); - - } finally { - try { - // Step 4: Notify callback after all processing is complete - // Call callback with the distributed event (original or error) - if (eventToDistribute != null) { - callback.onEventProcessed(taskId, eventToDistribute); - - // Step 5: If this is a final event, notify task finalization - // Only for successful persistence (not for errors) - if (eventToDistribute == event && isFinalEvent(event)) { - callback.onTaskFinalized(taskId); - } - } - } finally { - // ALWAYS release semaphore, even if processing fails - // Balances the acquire() in MainQueue.enqueueEvent() - mainQueue.releaseSemaphore(); - } - } - } - - /** - * Updates TaskStore using TaskManager.process(). - *

- * Creates a temporary TaskManager instance for this event and delegates to its process() method, - * which handles all event types (Task, TaskStatusUpdateEvent, TaskArtifactUpdateEvent). - * This leverages existing TaskManager logic for status updates, artifact appending, message history, etc. - *

- *

- * If persistence fails, the exception is propagated to processEvent() which distributes an - * InternalError to clients instead of the original event, ensuring "persist before visibility". - * See Gemini's comment: https://github.com/a2aproject/a2a-java/pull/515#discussion_r2604621833 - *

- * - * @param taskId the task ID - * @param event the event to persist - * @return true if the task reached a final state, false otherwise - * @throws InternalError if persistence fails - */ - private boolean updateTaskStore(String taskId, Event event, boolean isReplicated) throws InternalError { - try { - // Extract contextId from event (all relevant events have it) - String contextId = extractContextId(event); - - // Create temporary TaskManager instance for this event - TaskManager taskManager = new TaskManager(taskId, contextId, taskStore, null); - - // Use TaskManager.process() - handles all event types with existing logic - boolean isFinal = taskManager.process(event, isReplicated); - LOGGER.debug("TaskStore updated via TaskManager.process() for task {}: {} (final: {}, replicated: {})", - taskId, event.getClass().getSimpleName(), isFinal, isReplicated); - return isFinal; - } catch (InternalError e) { - LOGGER.error("Error updating TaskStore via TaskManager for task {}", taskId, e); - // Rethrow to prevent distributing unpersisted event to clients - throw e; - } catch (Exception e) { - LOGGER.error("Unexpected error updating TaskStore for task {}", taskId, e); - // Rethrow to prevent distributing unpersisted event to clients - throw new InternalError("TaskStore persistence failed: " + e.getMessage()); - } - } - - /** - * Sends push notification for the streaming event AFTER persistence. - *

- * This is called after updateTaskStore() to ensure the notification contains - * the latest persisted state, avoiding race conditions. - *

- *

- * CRITICAL: Push notifications are sent asynchronously in the background - * to avoid blocking event distribution to ChildQueues. The 83ms overhead from - * PushNotificationSender.sendNotification() was causing streaming delays. - *

- *

- * IMPORTANT: The event parameter is the actual event being processed. - * This ensures we send the event as it was when processed, not whatever state - * might exist in TaskStore when the async callback executes (subsequent events - * may have already updated the store). - *

- *

- * Supports all StreamingEventKind event types per A2A spec section 4.3.3: - * Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent. - * The event will be automatically wrapped in StreamResponse format by JsonUtil. - *

- *

- * NOTE: Tests can inject a synchronous executor via setPushNotificationExecutor() - * to ensure deterministic ordering of push notifications in the test environment. - *

- * - * @param taskId the task ID - * @param event the streaming event to send (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) - */ - private void sendPushNotification(String taskId, StreamingEventKind event) { - Runnable pushTask = () -> { - try { - if (event != null) { - LOGGER.debug("Sending push notification for task {}", taskId); - pushSender.sendNotification(event); - } else { - LOGGER.debug("Skipping push notification - event is null for task {}", taskId); - } - } catch (Exception e) { - LOGGER.error("Error sending push notification for task {}", taskId, e); - // Don't rethrow - push notifications are best-effort - } - }; - - // Use custom executor if set (for tests), otherwise use default ForkJoinPool (async) - if (pushNotificationExecutor != null) { - pushNotificationExecutor.execute(pushTask); - } else { - CompletableFuture.runAsync(pushTask); - } - } - - /** - * Extracts contextId from an event. - * Returns null if the event type doesn't have a contextId (e.g., Message). - */ - @Nullable - private String extractContextId(Event event) { - if (event instanceof Task task) { - return task.contextId(); - } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { - return statusUpdate.contextId(); - } else if (event instanceof TaskArtifactUpdateEvent artifactUpdate) { - return artifactUpdate.contextId(); - } - // Message and other events don't have contextId - return null; - } - - /** - * Checks if an event represents a final task state. - * - * @param event the event to check - * @return true if the event represents a final state (COMPLETED, FAILED, CANCELED, REJECTED, UNKNOWN, or A2AError) - */ - private boolean isFinalEvent(Event event) { - if (event instanceof Task task) { - return task.status() != null && task.status().state() != null - && task.status().state().isFinal(); - } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { - return statusUpdate.isFinal(); - } else if (event instanceof A2AError) { - // A2AError events are terminal - they trigger FAILED state transition - return true; - } - return false; - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java deleted file mode 100644 index b0a9adbce..000000000 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorCallback.java +++ /dev/null @@ -1,66 +0,0 @@ -package io.a2a.server.events; - -import io.a2a.spec.Event; - -/** - * Callback interface for MainEventBusProcessor events. - *

- * This interface is primarily intended for testing, allowing tests to synchronize - * with the asynchronous MainEventBusProcessor. Production code should not rely on this. - *

- * Usage in tests: - *
- * {@code
- * @Inject
- * MainEventBusProcessor processor;
- *
- * @BeforeEach
- * void setUp() {
- *     CountDownLatch latch = new CountDownLatch(3);
- *     processor.setCallback(new MainEventBusProcessorCallback() {
- *         public void onEventProcessed(String taskId, Event event) {
- *             latch.countDown();
- *         }
- *     });
- * }
- *
- * @AfterEach
- * void tearDown() {
- *     processor.setCallback(null); // Reset to NOOP
- * }
- * }
- * 
- */ -public interface MainEventBusProcessorCallback { - - /** - * Called after an event has been fully processed (persisted, notification sent, distributed to children). - * - * @param taskId the task ID - * @param event the event that was processed - */ - void onEventProcessed(String taskId, Event event); - - /** - * Called when a task reaches a final state (COMPLETED, FAILED, CANCELED, REJECTED). - * - * @param taskId the task ID that was finalized - */ - void onTaskFinalized(String taskId); - - /** - * No-op implementation that does nothing. - * Used as the default callback to avoid null checks. - */ - MainEventBusProcessorCallback NOOP = new MainEventBusProcessorCallback() { - @Override - public void onEventProcessed(String taskId, Event event) { - // No-op - } - - @Override - public void onTaskFinalized(String taskId) { - // No-op - } - }; -} diff --git a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java b/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java deleted file mode 100644 index ba4b300be..000000000 --- a/server-common/src/main/java/io/a2a/server/events/MainEventBusProcessorInitializer.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.a2a.server.events; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.context.Initialized; -import jakarta.enterprise.event.Observes; -import jakarta.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Portable CDI initializer for MainEventBusProcessor. - *

- * This bean observes the ApplicationScoped initialization event and injects - * MainEventBusProcessor, which triggers its eager creation and starts the background thread. - *

- *

- * This approach is portable across all Jakarta CDI implementations (Weld, OpenWebBeans, Quarkus, etc.) - * and ensures MainEventBusProcessor starts automatically when the application starts. - *

- */ -@ApplicationScoped -public class MainEventBusProcessorInitializer { - private static final Logger LOGGER = LoggerFactory.getLogger(MainEventBusProcessorInitializer.class); - - @Inject - MainEventBusProcessor processor; - - /** - * Observes ApplicationScoped initialization to force eager creation of MainEventBusProcessor. - * The injection of MainEventBusProcessor in this bean triggers its creation, and calling - * ensureStarted() forces the CDI proxy to be resolved, which ensures @PostConstruct has been - * called and the background thread is running. - */ - void onStart(@Observes @Initialized(ApplicationScoped.class) Object event) { - if (processor != null) { - // Force proxy resolution to ensure @PostConstruct has been called - processor.ensureStarted(); - LOGGER.info("MainEventBusProcessor initialized and started"); - } else { - LOGGER.error("MainEventBusProcessor is null - initialization failed!"); - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/NoTaskQueueException.java b/server-common/src/main/java/io/a2a/server/events/NoTaskQueueException.java deleted file mode 100644 index 5783dd214..000000000 --- a/server-common/src/main/java/io/a2a/server/events/NoTaskQueueException.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.a2a.server.events; - -/** - * Exception thrown when attempting to access a task queue that does not exist. - *

- * This exception is typically thrown when trying to retrieve or operate on - * an event queue for a task that has not been created or has been removed. - *

- */ -public class NoTaskQueueException extends RuntimeException { - /** - * Creates a NoTaskQueueException with no message. - */ - public NoTaskQueueException() { - } - - /** - * Creates a NoTaskQueueException with the specified detail message. - * - * @param message the detail message - */ - public NoTaskQueueException(String message) { - super(message); - } - - /** - * Creates a NoTaskQueueException with the specified detail message and cause. - * - * @param message the detail message - * @param cause the cause - */ - public NoTaskQueueException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Creates a NoTaskQueueException with the specified cause. - * - * @param cause the cause - */ - public NoTaskQueueException(Throwable cause) { - super(cause); - } - - /** - * Creates a NoTaskQueueException with the specified message, cause, - * suppression enabled or disabled, and writable stack trace enabled or disabled. - * - * @param message the detail message - * @param cause the cause - * @param enableSuppression whether suppression is enabled or disabled - * @param writableStackTrace whether the stack trace should be writable - */ - public NoTaskQueueException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/QueueClosedEvent.java b/server-common/src/main/java/io/a2a/server/events/QueueClosedEvent.java deleted file mode 100644 index b18c1a47a..000000000 --- a/server-common/src/main/java/io/a2a/server/events/QueueClosedEvent.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.a2a.server.events; - -import io.a2a.spec.Event; - -/** - * Poison pill event used to signal that a queue has been closed. - *

- * When a MainQueue is closed on one node, this event is published to Kafka - * to notify all other nodes consuming replicated events that they should - * gracefully terminate their event streams for this task. - *

- *

- * This event implements the "poison pill" pattern - when EventConsumer - * encounters this event, it throws EventQueueClosedException to terminate - * the consumption loop and close the stream. - *

- *

- * Note: This is an internal event that is never sent to end clients. - * The EventConsumer intercepts this event and terminates the stream - * before it reaches the client. - *

- */ -public class QueueClosedEvent implements Event { - - private final String taskId; - - public QueueClosedEvent(String taskId) { - this.taskId = taskId; - } - - public String getTaskId() { - return taskId; - } - - @Override - public String toString() { - return "QueueClosedEvent{taskId='" + taskId + "'}"; - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/QueueManager.java b/server-common/src/main/java/io/a2a/server/events/QueueManager.java deleted file mode 100644 index 4ad30f0cb..000000000 --- a/server-common/src/main/java/io/a2a/server/events/QueueManager.java +++ /dev/null @@ -1,218 +0,0 @@ -package io.a2a.server.events; - -import org.jspecify.annotations.Nullable; - -/** - * Manages {@link EventQueue} lifecycle for task-based event routing and consumption. - *

- * The QueueManager is responsible for creating, storing, and managing event queues that - * coordinate asynchronous communication between agent executors (producers) and transport - * consumers. It supports both simple in-memory queuing and sophisticated patterns like - * queue tapping for resubscription and distributed event replication. - *

- * - *

Queue Architecture

- *
    - *
  • MainQueue: Primary queue for a task, created by {@link #createOrTap(String)}
  • - *
  • ChildQueue: Subscriber view created by {@link #tap(String)}, receives copies of parent events
  • - *
  • One MainQueue per task, multiple ChildQueues for concurrent consumers (resubscription, cancellation)
  • - *
  • Events enqueued to MainQueue are automatically distributed to all active ChildQueues
  • - *
- * - *

Queue Lifecycle

- *
    - *
  1. Creation: {@link #createOrTap(String)} creates MainQueue for new task or taps existing for resubscription
  2. - *
  3. Population: Agent enqueues events to MainQueue via {@link EventQueue#enqueueEvent(io.a2a.spec.Event)}
  4. - *
  5. Distribution: Events automatically copied to all ChildQueues
  6. - *
  7. Consumption: Consumers poll events from their queues (Main or Child)
  8. - *
  9. Closure: Queue closes on final event (COMPLETED/FAILED/CANCELED) or explicit close
  10. - *
  11. Cleanup: MainQueue removed from manager when all ChildQueues close and task is finalized
  12. - *
- * - *

Default Implementation

- * {@link InMemoryQueueManager} provides the standard implementation: - *
    - *
  • Stores queues in thread-safe {@link java.util.concurrent.ConcurrentHashMap}
  • - *
  • Integrates with {@link io.a2a.server.tasks.TaskStateProvider} for cleanup decisions
  • - *
  • Removes queues when tasks enter final state (COMPLETED/FAILED/CANCELED)
  • - *
  • Supports queue tapping for resubscription scenarios
  • - *
- * - *

Alternative Implementations

- *
    - *
  • extras/queue-manager-replicated: Kafka-based replication for multi-instance deployments
  • - *
- * Replicated implementations enable event distribution across server instances for high - * availability and load balancing. - * - *

Tapping Pattern (Resubscription)

- * Tapping creates a ChildQueue that receives future events from an ongoing task: - *
{@code
- * // Client disconnects and later reconnects
- * EventQueue childQueue = queueManager.tap(taskId);
- * if (childQueue != null) {
- *     // Receive events from this point forward
- *     // (Historical events before tap are not replayed)
- * }
- * }
- * Use cases: - *
    - *
  • Resubscribing to ongoing tasks after disconnect
  • - *
  • Canceling tasks while still receiving status updates
  • - *
  • Multiple concurrent consumers of the same task
  • - *
- * - *

CDI Extension Pattern

- *
{@code
- * @ApplicationScoped
- * @Alternative
- * @Priority(50)  // Higher than default InMemoryQueueManager
- * public class KafkaQueueManager implements QueueManager {
- *     // Custom implementation with event replication
- * }
- * }
- * - *

Thread Safety

- * All methods must be thread-safe. Multiple threads may call {@code createOrTap()}, - * {@code tap()}, and {@code close()} concurrently for different tasks. - * - * @see EventQueue - * @see InMemoryQueueManager - * @see io.a2a.server.tasks.TaskStateProvider - * @see io.a2a.server.requesthandlers.DefaultRequestHandler - */ -public interface QueueManager { - - /** - * Adds a queue to the manager with the given task ID. - *

- * Throws {@link TaskQueueExistsException} if a queue already exists for this task. - * Typically used internally - prefer {@link #createOrTap(String)} for most use cases. - *

- * - * @param taskId the task identifier - * @param queue the queue to add - * @throws TaskQueueExistsException if queue already exists for this task ID - */ - void add(String taskId, EventQueue queue); - - /** - * Retrieves the MainQueue for a task, if it exists. - *

- * Returns the primary queue for the task. Does not create a new queue if none exists. - *

- * - * @param taskId the task identifier - * @return the MainQueue, or null if no queue exists for this task - */ - @Nullable EventQueue get(String taskId); - - /** - * Creates a ChildQueue that receives copies of events from the MainQueue. - *

- * Use this for: - *

    - *
  • Resubscribing to an ongoing task (receive future events)
  • - *
  • Canceling a task while still receiving status updates
  • - *
  • Multiple concurrent consumers of the same task
  • - *
- *

- * The ChildQueue receives events enqueued AFTER it's created. Historical events - * are not replayed. - * - * @param taskId the task identifier - * @return a ChildQueue that receives future events, or null if the MainQueue doesn't exist - */ - @Nullable EventQueue tap(String taskId); - - /** - * Closes and removes the queue for a task. - *

- * This closes the MainQueue and all ChildQueues, then removes it from the manager. - * Called during cleanup after task completion or error conditions. - *

- * - * @param taskId the task identifier - */ - void close(String taskId); - - /** - * Creates a MainQueue if none exists, or taps the existing queue to create a ChildQueue. - *

- * This is the primary method used by {@link io.a2a.server.requesthandlers.DefaultRequestHandler}: - *

    - *
  • New task: Creates and returns a MainQueue
  • - *
  • Resubscription: Taps existing MainQueue and returns a ChildQueue
  • - *
- * - * @param taskId the task identifier - * @return a MainQueue (if new task) or ChildQueue (if tapping existing) - */ - EventQueue createOrTap(String taskId); - - /** - * Waits for the queue's consumer polling to start. - *

- * Used internally to ensure the consumer is ready before the agent starts - * enqueueing events, avoiding race conditions where events might be enqueued - * before the consumer begins polling. - *

- * - * @param eventQueue the queue to wait for - * @throws InterruptedException if interrupted while waiting - */ - void awaitQueuePollerStart(EventQueue eventQueue) throws InterruptedException; - - /** - * Returns an EventQueueBuilder for creating queues with task-specific configuration. - *

- * Implementations can override to provide custom queue configurations per task, - * such as different capacities, hooks, or event processors. - *

- *

- * Default implementation returns a standard builder with no customization. - *

- * - * @param taskId the task ID for context (may be used to customize queue configuration) - * @return a builder for creating event queues - */ - default EventQueue.EventQueueBuilder getEventQueueBuilder(String taskId) { - throw new UnsupportedOperationException( - "QueueManager implementations must override getEventQueueBuilder() to provide MainEventBus" - ); - } - - /** - * Creates a base EventQueueBuilder with standard configuration for this QueueManager. - * This method provides the foundation for creating event queues with proper configuration - * (MainEventBus, TaskStateProvider, cleanup callbacks, etc.). - *

- * QueueManager implementations that use custom factories can call this method directly - * to get the base builder without going through the factory (which could cause infinite - * recursion if the factory delegates back to getEventQueueBuilder()). - *

- *

- * Callers can then add additional configuration (hooks, callbacks) before building the queue. - *

- * - * @param taskId the task ID for the queue - * @return a builder with base configuration specific to this QueueManager implementation - */ - default EventQueue.EventQueueBuilder createBaseEventQueueBuilder(String taskId) { - throw new UnsupportedOperationException( - "QueueManager implementations must override createBaseEventQueueBuilder() to provide MainEventBus" - ); - } - - /** - * Returns the number of active ChildQueues for a task. - *

- * Used for testing to verify reference counting and queue lifecycle management. - * In production, indicates how many consumers are actively subscribed to a task's events. - *

- * - * @param taskId the task ID - * @return number of active child queues, or -1 if the MainQueue doesn't exist - */ - int getActiveChildQueueCount(String taskId); -} diff --git a/server-common/src/main/java/io/a2a/server/events/TaskQueueExistsException.java b/server-common/src/main/java/io/a2a/server/events/TaskQueueExistsException.java deleted file mode 100644 index bfd429277..000000000 --- a/server-common/src/main/java/io/a2a/server/events/TaskQueueExistsException.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.a2a.server.events; - -public class TaskQueueExistsException extends RuntimeException { - public TaskQueueExistsException() { - } - - public TaskQueueExistsException(String message) { - super(message); - } - - public TaskQueueExistsException(String message, Throwable cause) { - super(message, cause); - } - - public TaskQueueExistsException(Throwable cause) { - super(cause); - } - - public TaskQueueExistsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/server-common/src/main/java/io/a2a/server/events/package-info.java b/server-common/src/main/java/io/a2a/server/events/package-info.java deleted file mode 100644 index 912717787..000000000 --- a/server-common/src/main/java/io/a2a/server/events/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.events; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java b/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java deleted file mode 100644 index 45e0e3ac2..000000000 --- a/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java +++ /dev/null @@ -1,71 +0,0 @@ -package io.a2a.server.extensions; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import io.a2a.server.ServerCallContext; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.ExtensionSupportRequiredError; -import org.jspecify.annotations.Nullable; - -public class A2AExtensions { - - public static Set getRequestedExtensions(List values) { - Set extensions = new HashSet<>(); - if (values == null) { - return extensions; - } - - for (String value : values) { - if (value != null) { - // Split by comma and trim whitespace - String[] parts = value.split(","); - for (String part : parts) { - String trimmed = part.trim(); - if (!trimmed.isEmpty()) { - extensions.add(trimmed); - } - } - } - } - - return extensions; - } - - public static @Nullable AgentExtension findExtensionByUri(AgentCard card, String uri) { - if (card.capabilities() == null || card.capabilities().extensions() == null) { - return null; - } - for (AgentExtension extension : card.capabilities().extensions()) { - if (extension.uri().equals(uri)) { - return extension; - } - } - return null; - } - - /** - * Validates that all required extensions declared in the AgentCard are requested by the client. - * - * @param agentCard the agent card containing extension declarations - * @param context the server call context containing requested extensions - * @throws ExtensionSupportRequiredError if a required extension is not requested - */ - public static void validateRequiredExtensions(AgentCard agentCard, ServerCallContext context) - throws ExtensionSupportRequiredError { - if (agentCard.capabilities() == null || agentCard.capabilities().extensions() == null) { - return; - } - - for (AgentExtension extension : agentCard.capabilities().extensions()) { - if (extension.required() && !context.isExtensionRequested(extension.uri())) { - throw new ExtensionSupportRequiredError( - null, - "Required extension '" + extension.uri() + "' was not requested by the client", - null); - } - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/extensions/package-info.java b/server-common/src/main/java/io/a2a/server/extensions/package-info.java deleted file mode 100644 index aa966d4a2..000000000 --- a/server-common/src/main/java/io/a2a/server/extensions/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.extensions; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/package-info.java b/server-common/src/main/java/io/a2a/server/package-info.java deleted file mode 100644 index a2474e4c1..000000000 --- a/server-common/src/main/java/io/a2a/server/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java deleted file mode 100644 index 2023fc7ac..000000000 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java +++ /dev/null @@ -1,1132 +0,0 @@ -package io.a2a.server.requesthandlers; - -import static io.a2a.server.util.async.AsyncUtils.convertingProcessor; -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; -import static io.a2a.server.util.async.AsyncUtils.processor; -import static java.util.concurrent.TimeUnit.SECONDS; - -import java.time.Instant; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; - -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.ServerCallContext; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.agentexecution.SimpleRequestContextBuilder; -import io.a2a.server.config.A2AConfigProvider; -import io.a2a.server.events.EnhancedRunnable; -import io.a2a.server.events.EventConsumer; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.server.tasks.ResultAggregator; -import io.a2a.server.tasks.TaskManager; -import io.a2a.server.tasks.TaskStore; -import io.a2a.server.util.async.EventConsumerExecutorProducer.EventConsumerExecutor; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.A2AError; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.Event; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.UnsupportedOperationError; - -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Central request orchestrator that coordinates transport requests with agent execution, - * task persistence, event routing, and push notifications. - *

- * This class is the core of the A2A server runtime. It receives requests from transport - * layers (JSON-RPC, gRPC, REST), executes user-provided {@link AgentExecutor} logic - * asynchronously, manages event queues for response streaming, and ensures task state - * is persisted through {@link TaskStore}. - *

- * - *

Architecture Overview

- *
- * Transport Layer (JSON-RPC/gRPC/REST)
- *     ↓ calls DefaultRequestHandler methods
- * DefaultRequestHandler (orchestrates)
- *     ↓
- * ┌─────────────┬──────────────┬─────────────────┬──────────────────┐
- * │ AgentExecutor│  TaskStore   │  QueueManager   │ PushNotification │
- * │ (user logic) │ (persistence)│ (event routing) │ (notifications)  │
- * └─────────────┴──────────────┴─────────────────┴──────────────────┘
- * 
- * - *

Request Flow - Blocking Mode (onMessageSend)

- *
    - *
  1. Transport calls {@link #onMessageSend(MessageSendParams, ServerCallContext)}
  2. - *
  3. Initialize {@link TaskManager} and {@link RequestContext}
  4. - *
  5. Create or tap {@link EventQueue} via {@link QueueManager}
  6. - *
  7. Execute {@link AgentExecutor#execute(RequestContext, AgentEmitter)} asynchronously in background thread pool
  8. - *
  9. Consume events from queue on Vert.x worker thread via {@link EventConsumer}
  10. - *
  11. For blocking=true: wait for agent completion and full event consumption
  12. - *
  13. Return {@link Task} or {@link Message} to transport
  14. - *
  15. Cleanup queue and agent future in background
  16. - *
- * - *

Request Flow - Streaming Mode (onMessageSendStream)

- *
    - *
  1. Transport calls {@link #onMessageSendStream(MessageSendParams, ServerCallContext)}
  2. - *
  3. Initialize components (same as blocking)
  4. - *
  5. Execute {@link AgentExecutor#execute(RequestContext, AgentEmitter)} asynchronously
  6. - *
  7. Return {@link java.util.concurrent.Flow.Publisher Flow.Publisher}<StreamingEventKind> immediately
  8. - *
  9. Events stream to client as they arrive in the queue
  10. - *
  11. On client disconnect: continue consumption in background (fire-and-forget)
  12. - *
  13. Cleanup after streaming completes
  14. - *
- * - *

Queue Lifecycle Management

- *
    - *
  • {@link QueueManager#createOrTap(String)} creates a MainQueue (new task) or ChildQueue (resubscription)
  • - *
  • Agent enqueues events on background thread via {@link EventQueue#enqueueEvent(Event)}
  • - *
  • {@link EventConsumer} polls and processes events on Vert.x worker thread
  • - *
  • Queue closes automatically on final event (COMPLETED/FAILED/CANCELED)
  • - *
  • Cleanup waits for both agent execution AND event consumption to complete
  • - *
- * - *

Threading Model

- *
    - *
  • Vert.x worker threads: Execute request handler methods (onMessageSend, etc.)
  • - *
  • Agent-executor pool (@Internal): Execute {@link AgentExecutor#execute(RequestContext, AgentEmitter)}
  • - *
  • Background cleanup: {@link java.util.concurrent.CompletableFuture CompletableFuture} async tasks
  • - *
- *

- * Important: Avoid blocking operations on Vert.x worker threads - they are limited - * and shared across all requests. - *

- * - *

Blocking vs Streaming

- *
    - *
  • Blocking (configuration.blocking=true): Client waits for first event or final task state
  • - *
  • Streaming: Client receives events as they arrive via reactive streams
  • - *
  • Both modes support fire-and-forget (agent continues after client disconnect)
  • - *
  • Configurable timeouts via {@code a2a.blocking.agent.timeout.seconds} and - * {@code a2a.blocking.consumption.timeout.seconds}
  • - *
- * - *

CDI Dependencies

- * This class is {@code @ApplicationScoped} and automatically injects: - *
    - *
  • {@link AgentExecutor} - User-provided agent business logic (required)
  • - *
  • {@link TaskStore} - Task persistence (default: {@link io.a2a.server.tasks.InMemoryTaskStore})
  • - *
  • {@link QueueManager} - Event queue management (default: {@link io.a2a.server.events.InMemoryQueueManager})
  • - *
  • {@link PushNotificationConfigStore} - Push config storage (default: {@link io.a2a.server.tasks.InMemoryPushNotificationConfigStore})
  • - *
  • {@link PushNotificationSender} - Push notification delivery (default: {@link io.a2a.server.tasks.BasePushNotificationSender})
  • - *
  • {@link io.a2a.server.config.A2AConfigProvider} - Configuration values
  • - *
  • {@link java.util.concurrent.Executor} (@Internal) - Background thread pool
  • - *
- * - *

Extension Strategy

- * Users typically don't replace DefaultRequestHandler. Instead, provide custom implementations - * of its dependencies via CDI: - *
    - *
  • {@link AgentExecutor} (required) - Your agent business logic
  • - *
  • {@link TaskStore} (@Alternative @Priority) - Database persistence (see extras/task-store-database-jpa)
  • - *
  • {@link QueueManager} (@Alternative @Priority) - Replication support (see extras/queue-manager-replicated)
  • - *
  • {@link PushNotificationSender} (@Alternative @Priority) - Custom notification delivery
  • - *
- * - * @see RequestHandler - * @see AgentExecutor - * @see TaskStore - * @see QueueManager - * @see EventQueue - * @see TaskManager - */ -@ApplicationScoped -public class DefaultRequestHandler implements RequestHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRequestHandler.class); - - /** - * Separate logger for thread statistics diagnostic logging. - * This allows independent control of verbose thread pool monitoring without affecting - * general request handler logging. Enable with: logging.level.io.a2a.server.diagnostics.ThreadStats=DEBUG - */ - private static final Logger THREAD_STATS_LOGGER = LoggerFactory.getLogger("io.a2a.server.diagnostics.ThreadStats"); - - private static final String A2A_BLOCKING_AGENT_TIMEOUT_SECONDS = "a2a.blocking.agent.timeout.seconds"; - private static final String A2A_BLOCKING_CONSUMPTION_TIMEOUT_SECONDS = "a2a.blocking.consumption.timeout.seconds"; - - @Inject - A2AConfigProvider configProvider; - - /** - * Timeout in seconds to wait for agent execution to complete in blocking calls. - * This allows slow agents (LLM-based, data processing, external APIs) sufficient time. - *

- * Property: {@code a2a.blocking.agent.timeout.seconds}
- * Default: 30 seconds
- * Note: Property override requires a configurable {@link A2AConfigProvider} on the classpath - * (e.g., MicroProfileConfigProvider in reference implementations). - */ - int agentCompletionTimeoutSeconds; - - /** - * Timeout in seconds to wait for event consumption to complete in blocking calls. - * This ensures all events are processed and persisted before returning to client. - *

- * Property: {@code a2a.blocking.consumption.timeout.seconds}
- * Default: 5 seconds
- * Note: Property override requires a configurable {@link A2AConfigProvider} on the classpath - * (e.g., MicroProfileConfigProvider in reference implementations). - */ - int consumptionCompletionTimeoutSeconds; - - // Fields set by constructor injection cannot be final. We need a noargs constructor for - // Jakarta compatibility, and it seems that making fields set by constructor injection - // final, is not proxyable in all runtimes - private AgentExecutor agentExecutor; - private TaskStore taskStore; - private QueueManager queueManager; - private PushNotificationConfigStore pushConfigStore; - private MainEventBusProcessor mainEventBusProcessor; - private Supplier requestContextBuilder; - - private final ConcurrentMap> runningAgents = new ConcurrentHashMap<>(); - - - private Executor executor; - private Executor eventConsumerExecutor; - - /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. - */ - @SuppressWarnings("NullAway") - protected DefaultRequestHandler() { - // For CDI proxy creation - this.agentExecutor = null; - this.taskStore = null; - this.queueManager = null; - this.pushConfigStore = null; - this.mainEventBusProcessor = null; - this.requestContextBuilder = null; - this.executor = null; - this.eventConsumerExecutor = null; - } - - @Inject - public DefaultRequestHandler(AgentExecutor agentExecutor, TaskStore taskStore, - QueueManager queueManager, PushNotificationConfigStore pushConfigStore, - MainEventBusProcessor mainEventBusProcessor, - @Internal Executor executor, - @EventConsumerExecutor Executor eventConsumerExecutor) { - this.agentExecutor = agentExecutor; - this.taskStore = taskStore; - this.queueManager = queueManager; - this.pushConfigStore = pushConfigStore; - this.mainEventBusProcessor = mainEventBusProcessor; - this.executor = executor; - this.eventConsumerExecutor = eventConsumerExecutor; - // TODO In Python this is also a constructor parameter defaulting to this SimpleRequestContextBuilder - // implementation if the parameter is null. Skip that for now, since otherwise I get CDI errors, and - // I am unsure about the correct scope. - // Also reworked to make a Supplier since otherwise the builder gets polluted with wrong tasks - this.requestContextBuilder = () -> new SimpleRequestContextBuilder(taskStore, false); - } - - @PostConstruct - void initConfig() { - agentCompletionTimeoutSeconds = Integer.parseInt( - configProvider.getValue(A2A_BLOCKING_AGENT_TIMEOUT_SECONDS)); - consumptionCompletionTimeoutSeconds = Integer.parseInt( - configProvider.getValue(A2A_BLOCKING_CONSUMPTION_TIMEOUT_SECONDS)); - } - - - /** - * For testing - */ - public static DefaultRequestHandler create(AgentExecutor agentExecutor, TaskStore taskStore, - QueueManager queueManager, PushNotificationConfigStore pushConfigStore, - MainEventBusProcessor mainEventBusProcessor, - Executor executor, Executor eventConsumerExecutor) { - DefaultRequestHandler handler = - new DefaultRequestHandler(agentExecutor, taskStore, queueManager, pushConfigStore, - mainEventBusProcessor, executor, eventConsumerExecutor); - handler.agentCompletionTimeoutSeconds = 5; - handler.consumptionCompletionTimeoutSeconds = 2; - - return handler; - } - - @Override - public Task onGetTask(TaskQueryParams params, ServerCallContext context) throws A2AError { - LOGGER.debug("onGetTask {}", params.id()); - Task task = taskStore.get(params.id()); - if (task == null) { - LOGGER.debug("No task found for {}. Throwing TaskNotFoundError", params.id()); - throw new TaskNotFoundError(); - } - task = limitTaskHistory(task, params.historyLength()); - LOGGER.debug("Task found {}", task); - return task; - } - - /** - * Limits the history of a task to the most recent N messages. - * - * @param task the task to limit - * @param historyLength the maximum number of recent messages to keep (0 or negative = unlimited) - * @return the task with limited history, or the original task if no limiting needed - */ - private static Task limitTaskHistory(Task task, @Nullable Integer historyLength) { - if (task.history() == null || historyLength == null || historyLength >= task.history().size()) { - return task; - } - // Keep only the most recent historyLength messages - List limitedHistory = task.history().subList( - task.history().size() - historyLength, - task.history().size()); - return Task.builder(task) - .history(limitedHistory) - .build(); - } - - @Override - public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext context) throws A2AError { - LOGGER.debug("onListTasks with contextId={}, status={}, pageSize={}, pageToken={}, statusTimestampAfter={}", - params.contextId(), params.status(), params.pageSize(), params.pageToken(), params.statusTimestampAfter()); - - // Validate statusTimestampAfter timestamp if provided - if (params.statusTimestampAfter() != null) { - // Check if timestamp is in the future (optional validation per spec) - Instant now = Instant.now(); - if (params.statusTimestampAfter().isAfter(now)) { - Map errorData = new HashMap<>(); - errorData.put("parameter", "lastUpdatedAfter"); - errorData.put("reason", "Timestamp cannot be in the future"); - throw new InvalidParamsError(null, "Invalid params", errorData); - } - // Check that timestamp is not negative - long millis = params.statusTimestampAfter().toEpochMilli(); - if (millis < 0L) { - Map errorData = new HashMap<>(); - errorData.put("parameter", "statusTimestampAfter"); - errorData.put("reason", "Must be a non-negative timestamp value, got: " + millis); - throw new InvalidParamsError(null, "Invalid params", errorData); - } - } - - ListTasksResult result = taskStore.list(params); - LOGGER.debug("Found {} tasks (total: {})", result.pageSize(), result.totalSize()); - return result; - } - - @Override - public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws A2AError { - Task task = taskStore.get(params.id()); - if (task == null) { - throw new TaskNotFoundError(); - } - - // Check if task is in a non-cancelable state (completed, canceled, failed, rejected) - if (task.status().state().isFinal()) { - throw new TaskNotCancelableError( - "Task cannot be canceled - current state: " + task.status().state()); - } - - TaskManager taskManager = new TaskManager( - task.id(), - task.contextId(), - taskStore, - null); - - ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); - - EventQueue queue = queueManager.createOrTap(task.id()); - RequestContext cancelRequestContext = requestContextBuilder.get() - .setTaskId(task.id()) - .setContextId(task.contextId()) - .setTask(task) - .setServerCallContext(context) - .build(); - AgentEmitter emitter = new AgentEmitter(cancelRequestContext, queue); - try { - agentExecutor.cancel(cancelRequestContext, emitter); - } catch (TaskNotCancelableError e) { - // Expected error - log at INFO level - LOGGER.info("Task {} is not cancelable", task.id()); - throw e; - } catch (A2AError e) { - // Other A2A errors - log at WARN level with stack trace - LOGGER.warn("Agent cancellation threw A2AError for task {}: {} - {}", - task.id(), e.getClass().getSimpleName(), e.getMessage(), e); - throw e; - } catch (Exception e) { - // Unexpected errors - log at ERROR level - LOGGER.error("Agent cancellation threw unexpected exception for task {}", task.id(), e); - throw new io.a2a.spec.InternalError("Agent cancellation failed: " + e.getMessage()); - } - - Optional.ofNullable(runningAgents.get(task.id())) - .ifPresent(cf -> cf.cancel(true)); - - EventConsumer consumer = new EventConsumer(queue); - EventKind type = resultAggregator.consumeAll(consumer); - if (!(type instanceof Task tempTask)) { - throw new InternalError("Agent did not return valid response for cancel"); - } - - // Verify task was actually canceled (not completed concurrently) - if (tempTask.status().state() != TaskState.TASK_STATE_CANCELED) { - throw new TaskNotCancelableError( - "Task cannot be canceled - current state: " + tempTask.status().state()); - } - - return tempTask; - } - - @Override - @SuppressWarnings("NullAway") - public EventKind onMessageSend(MessageSendParams params, ServerCallContext context) throws A2AError { - LOGGER.debug("onMessageSend - task: {}; context {}", params.message().taskId(), params.message().contextId()); - - // Build MessageSendSetup which creates RequestContext with real taskId (auto-generated if needed) - MessageSendSetup mss = initMessageSend(params, context); - - // Use the taskId from RequestContext for queue management (no temp ID needed!) - // RequestContext.build() guarantees taskId is non-null via checkOrGenerateTaskId() - String queueTaskId = java.util.Objects.requireNonNull( - mss.requestContext.getTaskId(), "TaskId must be non-null after RequestContext.build()"); - LOGGER.debug("Queue taskId: {}", queueTaskId); - - // Create queue with real taskId (no tempId parameter needed) - EventQueue queue = queueManager.createOrTap(queueTaskId); - final java.util.concurrent.atomic.AtomicReference<@NonNull String> taskId = new java.util.concurrent.atomic.AtomicReference<>(queueTaskId); - ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); - - // Default to blocking=false per A2A spec (return after task creation) - boolean blocking = params.configuration() != null && Boolean.TRUE.equals(params.configuration().blocking()); - - // Log blocking behavior from client request - if (params.configuration() != null && params.configuration().blocking() != null) { - LOGGER.debug("DefaultRequestHandler: Client requested blocking={} for task {}", - params.configuration().blocking(), taskId.get()); - } else if (params.configuration() != null) { - LOGGER.debug("DefaultRequestHandler: Client sent configuration but blocking=null, using default blocking={} for task {}", blocking, taskId.get()); - } else { - LOGGER.debug("DefaultRequestHandler: Client sent no configuration, using default blocking={} for task {}", blocking, taskId.get()); - } - LOGGER.debug("DefaultRequestHandler: Final blocking decision: {} for task {}", blocking, taskId.get()); - - boolean interruptedOrNonBlocking = false; - - // Create consumer BEFORE starting agent - callback is registered inside registerAndExecuteAgentAsync - EventConsumer consumer = new EventConsumer(queue); - - EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue, consumer.createAgentRunnableDoneCallback()); - - ResultAggregator.EventTypeAndInterrupt etai = null; - EventKind kind = null; // Declare outside try block so it's in scope for return - try { - - // Get agent future before consuming (for blocking calls to wait for agent completion) - CompletableFuture agentFuture = runningAgents.get(queueTaskId); - etai = resultAggregator.consumeAndBreakOnInterrupt(consumer, blocking); - - if (etai == null) { - LOGGER.debug("No result, throwing InternalError"); - throw new InternalError("No result"); - } - interruptedOrNonBlocking = etai.interrupted(); - LOGGER.debug("DefaultRequestHandler: interruptedOrNonBlocking={} (blocking={}, eventType={})", - interruptedOrNonBlocking, blocking, kind != null ? kind.getClass().getSimpleName() : null); - - // For blocking calls that were interrupted (returned on first event), - // wait for agent execution and event processing BEFORE returning to client. - // This ensures the returned Task has all artifacts and current state. - // We do this HERE (not in ResultAggregator) to avoid blocking Vert.x worker threads - // during the consumption loop itself. - kind = etai.eventType(); - - // No ID switching needed - agent uses context.getTaskId() which is the same as queue key - - // Store push notification config for newly created tasks (mirrors streaming logic) - // Only for NEW tasks - existing tasks are handled by initMessageSend() - if (mss.task() == null && kind instanceof Task createdTask && shouldAddPushInfo(params)) { - LOGGER.debug("Storing push notification config for new task {} (original taskId from params: {})", - createdTask.id(), params.message().taskId()); - pushConfigStore.setInfo(createdTask.id(), params.configuration().pushNotificationConfig()); - } - - if (blocking && interruptedOrNonBlocking) { - // For blocking calls: ensure all consumed events are persisted to TaskStore before returning - // Order of operations is critical to avoid circular dependency and race conditions: - // 1. Wait for agent to finish enqueueing events (or timeout) - // 2. Close the queue to signal consumption can complete - // 3. Wait for consumption to finish processing events - // 4. (Implicit) MainEventBusProcessor persistence guarantee via consumption completion - // 5. Fetch current task state from TaskStore (includes all consumed & persisted events) - LOGGER.debug("DefaultRequestHandler: Entering blocking fire-and-forget handling for task {}", taskId.get()); - - try { - // Step 1: Wait for agent to finish (with configurable timeout) - if (agentFuture != null) { - try { - agentFuture.get(agentCompletionTimeoutSeconds, SECONDS); - LOGGER.debug("DefaultRequestHandler: Step 1 - Agent completed for task {}", taskId.get()); - } catch (java.util.concurrent.TimeoutException e) { - // Agent still running after timeout - that's fine, events already being processed - LOGGER.debug("DefaultRequestHandler: Step 1 - Agent still running for task {} after {}s timeout", - taskId.get(), agentCompletionTimeoutSeconds); - } - } - - // Step 2: Close the queue to signal consumption can complete - // For fire-and-forget tasks, there's no final event, so we need to close the queue - // This allows EventConsumer.consumeAll() to exit - queue.close(false, false); // graceful close, don't notify parent yet - LOGGER.debug("DefaultRequestHandler: Step 2 - Closed queue for task {} to allow consumption completion", taskId.get()); - - // Step 3: Wait for consumption to complete (now that queue is closed) - if (etai.consumptionFuture() != null) { - etai.consumptionFuture().get(consumptionCompletionTimeoutSeconds, SECONDS); - LOGGER.debug("DefaultRequestHandler: Step 3 - Consumption completed for task {}", taskId.get()); - } - - // Step 4: Implicit guarantee of persistence via consumption completion - // We do NOT add an explicit wait for MainEventBusProcessor here because: - // 1. MainEventBusProcessor persists BEFORE distributing to ChildQueues - // 2. Step 3 (consumption completion) already guarantees all consumed events are persisted - // 3. Adding another explicit synchronization point would require exposing - // MainEventBusProcessor internals and blocking event loop threads - // - // Note: For fire-and-forget tasks, if the agent is still running after Step 1 timeout, - // it may enqueue additional events. These will be persisted asynchronously but won't - // be included in the task state returned to the client (already consumed in Step 3). - - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - String msg = String.format("Error waiting for task %s completion", taskId.get()); - LOGGER.warn(msg, e); - throw new InternalError(msg); - } catch (java.util.concurrent.ExecutionException e) { - String msg = String.format("Error during task %s execution", taskId.get()); - LOGGER.warn(msg, e.getCause()); - throw new InternalError(msg); - } catch (TimeoutException e) { - // Timeout from consumption future.get() - different from finalization timeout - String msg = String.format("Timeout waiting for task %s consumption", taskId.get()); - LOGGER.warn(msg, e); - throw new InternalError(msg); - } - - // Step 5: Fetch the current task state from TaskStore - // All events consumed in Step 3 are guaranteed persisted (MainEventBusProcessor - // ordering: persist → distribute → consume). This returns the persisted state - // including all consumed events and artifacts. - String nonNullTaskId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); - Task updatedTask = taskStore.get(nonNullTaskId); - if (updatedTask != null) { - kind = updatedTask; - LOGGER.debug("DefaultRequestHandler: Step 5 - Fetched current task for {} with state {} and {} artifacts", - taskId.get(), updatedTask.status().state(), - updatedTask.artifacts().size()); - } else { - LOGGER.warn("DefaultRequestHandler: Step 5 - Task {} not found in TaskStore!", taskId.get()); - } - } - String finalTaskId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); - if (kind instanceof Task taskResult && !finalTaskId.equals(taskResult.id())) { - throw new InternalError("Task ID mismatch in agent response"); - } - } finally { - // For non-blocking calls: close ChildQueue IMMEDIATELY to free EventConsumer thread - // CRITICAL: Must use immediate=true to clear the local queue, otherwise EventConsumer - // continues polling until queue drains naturally, holding executor thread. - // Immediate close clears pending events and triggers EventQueueClosedException on next poll. - // Events continue flowing through MainQueue → MainEventBus → TaskStore. - if (!blocking && etai != null && etai.interrupted()) { - LOGGER.debug("DefaultRequestHandler: Non-blocking call in finally - closing ChildQueue IMMEDIATELY for task {} to free EventConsumer", taskId.get()); - queue.close(true); // immediate=true: clear queue and free EventConsumer - } - - // Remove agent from map immediately to prevent accumulation - CompletableFuture agentFuture = runningAgents.remove(queueTaskId); - String cleanupTaskId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); - LOGGER.debug("Removed agent for task {} from runningAgents in finally block, size after: {}", cleanupTaskId, runningAgents.size()); - - // Cleanup as background task to avoid blocking Vert.x threads - // Pass the consumption future to ensure cleanup waits for background consumption to complete - cleanupProducer(agentFuture, etai != null ? etai.consumptionFuture() : null, cleanupTaskId, queue, false) - .whenComplete((res, err) -> { - if (err != null) { - LOGGER.error("Error during async cleanup for task {}", taskId.get(), err); - } - }); - } - - LOGGER.debug("Returning: {}", kind); - return kind; - } - - @Override - @SuppressWarnings("NullAway") - public Flow.Publisher onMessageSendStream( - MessageSendParams params, ServerCallContext context) throws A2AError { - LOGGER.debug("onMessageSendStream START - task: {}; context: {}; runningAgents: {}", - params.message().taskId(), params.message().contextId(), runningAgents.size()); - - // Build MessageSendSetup which creates RequestContext with real taskId (auto-generated if needed) - MessageSendSetup mss = initMessageSend(params, context); - - // Use the taskId from RequestContext for queue management (no temp ID needed!) - // RequestContext.build() guarantees taskId is non-null via checkOrGenerateTaskId() - String queueTaskId = java.util.Objects.requireNonNull( - mss.requestContext.getTaskId(), "TaskId must be non-null after RequestContext.build()"); - final AtomicReference<@NonNull String> taskId = new AtomicReference<>(queueTaskId); - - // Create queue with real taskId (no tempId parameter needed) - EventQueue queue = queueManager.createOrTap(queueTaskId); - LOGGER.debug("Created/tapped queue for task {}: {}", taskId.get(), queue); - - // Store push notification config SYNCHRONOUSLY for new tasks before agent starts - // This ensures config is available when MainEventBusProcessor sends push notifications - // For existing tasks, config is stored in initMessageSend() - if (mss.task() == null && shouldAddPushInfo(params)) { - // Satisfy Nullaway - Objects.requireNonNull(taskId.get(), "taskId was null"); - LOGGER.debug("Storing push notification config for new streaming task {} EARLY (original taskId from params: {})", - taskId.get(), params.message().taskId()); - pushConfigStore.setInfo(taskId.get(), params.configuration().pushNotificationConfig()); - } - - ResultAggregator resultAggregator = new ResultAggregator(mss.taskManager, null, executor, eventConsumerExecutor); - - // Create consumer BEFORE starting agent - callback is registered inside registerAndExecuteAgentAsync - EventConsumer consumer = new EventConsumer(queue); - - EnhancedRunnable producerRunnable = registerAndExecuteAgentAsync(queueTaskId, mss.requestContext, queue, consumer.createAgentRunnableDoneCallback()); - - // Store cancel callback in context for closeHandler to access - // When client disconnects, closeHandler can call this to stop EventConsumer polling loop - context.setEventConsumerCancelCallback(consumer::cancel); - - try { - Flow.Publisher results = resultAggregator.consumeAndEmit(consumer); - - // First process the items then convert to Event - Flow.Publisher processed = - processor(createTubeConfig(), results, ((errorConsumer, item) -> { - Event event = item.getEvent(); - if (event instanceof Task createdTask) { - // Verify task ID matches (should always match now - agent uses context.getTaskId()) - String currentId = Objects.requireNonNull(taskId.get(), "taskId cannot be null"); - if (!currentId.equals(createdTask.id())) { - errorConsumer.accept(new InternalError("Task ID mismatch: expected " + currentId + - " but got " + createdTask.id())); - } - } - return true; - })); - - // Then convert EventQueueItem -> Event - Flow.Publisher eventPublisher = convertingProcessor(processed, EventQueueItem::getEvent); - - Flow.Publisher finalPublisher = convertingProcessor(eventPublisher, event -> (StreamingEventKind) event); - - // Wrap publisher to detect client disconnect and immediately close ChildQueue - // This prevents ChildQueue backpressure from blocking MainEventBusProcessor - return subscriber -> { - String currentTaskId = taskId.get(); - LOGGER.debug("Creating subscription wrapper for task {}", currentTaskId); - finalPublisher.subscribe(new Flow.Subscriber() { - private Flow.@Nullable Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - LOGGER.debug("onSubscribe called for task {}", taskId.get()); - this.subscription = subscription; - // Wrap subscription to detect cancellation - subscriber.onSubscribe(new Flow.Subscription() { - @Override - public void request(long n) { - LOGGER.debug("Subscription.request({}) for task {}", n, taskId.get()); - subscription.request(n); - } - - @Override - public void cancel() { - LOGGER.debug("Client cancelled subscription for task {}, closing ChildQueue immediately", taskId.get()); - // Close ChildQueue immediately to prevent backpressure - // (clears queue and releases semaphore permits) - queue.close(true); // immediate=true - subscription.cancel(); - } - }); - } - - @Override - public void onNext(StreamingEventKind item) { - LOGGER.debug("onNext: {} for task {}", item.getClass().getSimpleName(), taskId.get()); - subscriber.onNext(item); - } - - @Override - public void onError(Throwable throwable) { - LOGGER.error("onError for task {}", taskId.get(), throwable); - subscriber.onError(throwable); - } - - @Override - public void onComplete() { - LOGGER.debug("onComplete for task {}", taskId.get()); - try { - subscriber.onComplete(); - } catch (IllegalStateException e) { - // Client already disconnected and response closed - this is expected - // for streaming responses where client disconnect closes ChildQueue. - // Log and ignore. - if (e.getMessage() != null && e.getMessage().contains("Response has already been written")) { - LOGGER.debug("Client disconnected before onComplete, response already closed for task {}", taskId.get()); - } else { - throw e; - } - } - } - }); - }; - } finally { - // Needed to satisfy Nullaway - String idOfTask = taskId.get(); - if (idOfTask != null) { - LOGGER.debug("onMessageSendStream FINALLY - task: {}; runningAgents: {}", - idOfTask, runningAgents.size()); - - // Remove agent from map immediately to prevent accumulation - CompletableFuture agentFuture = runningAgents.remove(idOfTask); - LOGGER.debug("Removed agent for task {} from runningAgents in finally block, size after: {}", taskId.get(), runningAgents.size()); - - cleanupProducer(agentFuture, null, idOfTask, queue, true) - .whenComplete((res, err) -> { - if (err != null) { - LOGGER.error("Error during async cleanup for streaming task {}", taskId.get(), err); - } - }); - } - } - } - - @Override - public TaskPushNotificationConfig onCreateTaskPushNotificationConfig( - TaskPushNotificationConfig params, ServerCallContext context) throws A2AError { - if (pushConfigStore == null) { - throw new UnsupportedOperationError(); - } - Task task = taskStore.get(params.taskId()); - if (task == null) { - throw new TaskNotFoundError(); - } - - PushNotificationConfig pushNotificationConfig = pushConfigStore.setInfo(params.taskId(), params.config()); - return new TaskPushNotificationConfig(params.taskId(), pushNotificationConfig, params.tenant()); - } - - @Override - public TaskPushNotificationConfig onGetTaskPushNotificationConfig( - GetTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { - if (pushConfigStore == null) { - throw new UnsupportedOperationError(); - } - Task task = taskStore.get(params.taskId()); - if (task == null) { - throw new TaskNotFoundError(); - } - - ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult = pushConfigStore.getInfo(new ListTaskPushNotificationConfigParams(params.taskId())); - if (listTaskPushNotificationConfigResult == null || listTaskPushNotificationConfigResult.isEmpty()) { - throw new InternalError("No push notification config found"); - } - - String configId = params.id(); - return new TaskPushNotificationConfig(params.taskId(), getPushNotificationConfig(listTaskPushNotificationConfigResult, configId), params.tenant()); - } - - private PushNotificationConfig getPushNotificationConfig(ListTaskPushNotificationConfigResult notificationConfigList, - String configId) { - for (TaskPushNotificationConfig notificationConfig : notificationConfigList.configs()) { - if (configId.equals(notificationConfig.config().id())) { - return notificationConfig.config(); - } - } - return notificationConfigList.configs().get(0).config(); - } - - @Override - public Flow.Publisher onSubscribeToTask(TaskIdParams params, ServerCallContext context) throws A2AError { - LOGGER.debug("onSubscribeToTask - taskId: {}", params.id()); - Task task = taskStore.get(params.id()); - if (task == null) { - throw new TaskNotFoundError(); - } - - TaskManager taskManager = new TaskManager(task.id(), task.contextId(), taskStore, null); - ResultAggregator resultAggregator = new ResultAggregator(taskManager, null, executor, eventConsumerExecutor); - EventQueue queue = queueManager.tap(task.id()); - LOGGER.debug("onSubscribeToTask - tapped queue: {}", queue != null ? System.identityHashCode(queue) : "null"); - - if (queue == null) { - // If task is in final state, queue legitimately doesn't exist anymore - if (task.status().state().isFinal()) { - throw new TaskNotFoundError(); - } - // For non-final tasks, recreate the queue so client can receive future events - // (Note: historical events from before queue closed are not available) - LOGGER.debug("Queue not found for active task {}, creating new queue for future events", task.id()); - queue = queueManager.createOrTap(task.id()); - } - - // Per A2A Protocol Spec 3.1.6 (Subscribe to Task): - // "The operation MUST return a Task object as the first event in the stream, - // representing the current state of the task at the time of subscription." - // Enqueue the current task state directly to this ChildQueue only (already persisted, no need for MainEventBus) - queue.enqueueEventLocalOnly(task); - LOGGER.debug("onSubscribeToTask - enqueued current task state as first event for taskId: {}", params.id()); - - EventConsumer consumer = new EventConsumer(queue); - Flow.Publisher results = resultAggregator.consumeAndEmit(consumer); - LOGGER.debug("onSubscribeToTask - returning publisher for taskId: {}", params.id()); - return convertingProcessor(results, item -> (StreamingEventKind) item.getEvent()); - } - - @Override - public ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig( - ListTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { - if (pushConfigStore == null) { - throw new UnsupportedOperationError(); - } - Task task = taskStore.get(params.id()); - if (task == null) { - throw new TaskNotFoundError(); - } - return pushConfigStore.getInfo(params); - } - - @Override - public void onDeleteTaskPushNotificationConfig( - DeleteTaskPushNotificationConfigParams params, ServerCallContext context) { - if (pushConfigStore == null) { - throw new UnsupportedOperationError(); - } - - Task task = taskStore.get(params.taskId()); - if (task == null) { - throw new TaskNotFoundError(); - } - - pushConfigStore.deleteInfo(params.taskId(), params.id()); - } - - private boolean shouldAddPushInfo(MessageSendParams params) { - return pushConfigStore != null && params.configuration() != null && params.configuration().pushNotificationConfig() != null; - } - - /** - * Register and execute the agent asynchronously in the agent-executor thread pool. - * - * Queue Lifecycle Architecture: - * - Agent-executor thread: Executes agent and enqueues events, returns immediately - * - Vert.x worker thread (consumer): Polls queue, processes events, closes queue on final event - * - Background cleanup: Manages ChildQueue/MainQueue lifecycle after agent completes - * - * This design avoids blocking agent-executor threads waiting for consumer polling to start, - * eliminating cascading delays when Vert.x worker threads are busy. - * - * @param doneCallback Callback to invoke when agent completes - MUST be added before starting CompletableFuture - */ - private EnhancedRunnable registerAndExecuteAgentAsync(String taskId, RequestContext requestContext, EventQueue queue, EnhancedRunnable.DoneCallback doneCallback) { - LOGGER.debug("Registering agent execution for task {}, runningAgents.size() before: {}", taskId, runningAgents.size()); - logThreadStats("AGENT START"); - EnhancedRunnable runnable = new EnhancedRunnable() { - @Override - public void run() { - LOGGER.debug("Agent execution starting for task {}", taskId); - AgentEmitter emitter = new AgentEmitter(requestContext, queue); - try { - agentExecutor.execute(requestContext, emitter); - } catch (A2AError e) { - // Log A2A errors at WARN level with full stack trace - // These are expected business errors but should be tracked - LOGGER.warn("Agent execution threw A2AError for task {}: {} - {}", - taskId, e.getClass().getSimpleName(), e.getMessage(), e); - emitter.fail(e); - } catch (RuntimeException e) { - // Log unexpected runtime exceptions at ERROR level - // These indicate bugs in agent implementation - LOGGER.error("Agent execution threw unexpected RuntimeException for task {}", taskId, e); - emitter.fail(new io.a2a.spec.InternalError("Agent execution failed: " + e.getMessage())); - } catch (Exception e) { - // Log other exceptions at ERROR level - LOGGER.error("Agent execution threw unexpected Exception for task {}", taskId, e); - emitter.fail(new io.a2a.spec.InternalError("Agent execution failed: " + e.getMessage())); - } - LOGGER.debug("Agent execution completed for task {}", taskId); - // The consumer (running on the Vert.x worker thread) handles queue lifecycle. - // This avoids blocking agent-executor threads waiting for worker threads. - } - }; - - // CRITICAL: Add callback BEFORE starting CompletableFuture to avoid race condition - // If agent completes very fast, whenComplete can fire before caller adds callbacks - runnable.addDoneCallback(doneCallback); - - // Mark as started to prevent further callback additions (enforced by runtime check) - runnable.markStarted(); - - CompletableFuture cf = CompletableFuture.runAsync(runnable, executor) - .whenComplete((v, err) -> { - if (err != null) { - LOGGER.error("Agent execution failed for task {}", taskId, err); - runnable.setError(err); - // Don't close queue here - let the consumer handle it via error callback - // This ensures the consumer (which may not have started polling yet) gets the error - } - // Queue lifecycle is managed by EventConsumer.consumeAll() - // which closes the queue on final events. - logThreadStats("AGENT COMPLETE END"); - runnable.invokeDoneCallbacks(); - }); - runningAgents.put(taskId, cf); - LOGGER.debug("Registered agent for task {}, runningAgents.size() after: {}", taskId, runningAgents.size()); - return runnable; - } - - private CompletableFuture cleanupProducer(@Nullable CompletableFuture agentFuture, @Nullable CompletableFuture consumptionFuture, String taskId, EventQueue queue, boolean isStreaming) { - LOGGER.debug("Starting cleanup for task {} (streaming={})", taskId, isStreaming); - logThreadStats("CLEANUP START"); - - if (agentFuture == null) { - LOGGER.debug("No running agent found for task {}, cleanup complete", taskId); - return CompletableFuture.completedFuture(null); - } - - // Wait for BOTH agent AND consumption to complete before cleanup - // This ensures TaskStore is fully updated before we check task finalization - CompletableFuture bothComplete = agentFuture; - if (consumptionFuture != null) { - bothComplete = CompletableFuture.allOf(agentFuture, consumptionFuture); - LOGGER.debug("Cleanup will wait for both agent and consumption to complete for task {}", taskId); - } - - return bothComplete.whenComplete((v, t) -> { - if (t != null) { - LOGGER.debug("Agent/consumption completed with error for task {}", taskId, t); - } else { - LOGGER.debug("Agent and consumption both completed successfully for task {}", taskId); - } - - if (isStreaming) { - // For streaming: EventConsumer handles queue closure via agentCompleted flag - // When agent completes, EventConsumer.agentCompleted is set to true via agent done callback - // EventConsumer drains remaining events from ChildQueue (waiting for MainEventBusProcessor) - // After poll timeout with agentCompleted=true, EventConsumer closes queue and completes stream - // This avoids race condition where cleanup closes queue before MainEventBusProcessor distributes events - LOGGER.debug("Streaming call for task {}: queue lifecycle managed by EventConsumer (agentCompleted flag)", taskId); - } else { - // For non-streaming: close the ChildQueue directly - // No EventConsumer polling, so we must close explicitly - // This triggers MainQueue.childClosing() which handles cleanup and poison pill generation - LOGGER.debug("Non-streaming call, closing ChildQueue for task {} (immediate=false, notifyParent=true)", taskId); - queue.close(false, true); - } - - // For replicated environments, the poison pill is now sent via CDI events - // When JpaDatabaseTaskStore.save() persists a final task, it fires TaskFinalizedEvent - // ReplicatedQueueManager.onTaskFinalized() observes AFTER_SUCCESS and sends poison pill - // This guarantees the transaction is committed before the poison pill is sent - LOGGER.debug("Queue cleanup completed for task {}", taskId); - - logThreadStats("CLEANUP END"); - }); - } - - private MessageSendSetup initMessageSend(MessageSendParams params, ServerCallContext context) { - // Build RequestContext FIRST to get the real taskId (auto-generated if not provided) - // This eliminates the need for temporary IDs - we use the same UUID throughout - RequestContext requestContext = requestContextBuilder.get() - .setParams(params) - .setTaskId(params.message().taskId()) // Use client's ID or let RequestContext generate - .setContextId(params.message().contextId()) - .setTask(null) // Will be set below after TaskManager retrieves it - .setServerCallContext(context) - .build(); - - // Get the actual taskId from RequestContext (either from client or auto-generated) - // RequestContext.build() guarantees taskId is non-null via checkOrGenerateTaskId() - String taskId = java.util.Objects.requireNonNull( - requestContext.getTaskId(), "TaskId must be non-null after RequestContext.build()"); - - // Create TaskManager with the real taskId - TaskManager taskManager = new TaskManager( - taskId, - params.message().contextId(), - taskStore, - params.message()); - - Task task = taskManager.getTask(); - if (task != null) { - LOGGER.debug("Found task updating with message {}", params.message()); - task = taskManager.updateWithMessage(params.message(), task); - - if (pushConfigStore != null && params.configuration() != null && params.configuration().pushNotificationConfig() != null) { - LOGGER.debug("Adding push info"); - pushConfigStore.setInfo(task.id(), params.configuration().pushNotificationConfig()); - } - } - - // Only rebuild RequestContext if we have a task to add, or if taskId was auto-generated - // and doesn't match the original message (to update params with generated taskId) - boolean taskIdChanged = !taskId.equals(params.message().taskId()); - - if (task != null || taskIdChanged) { - MessageSendParams paramsToUse; - - if (taskIdChanged) { - // Update message to include the taskId (handles auto-generated case) - // This prevents "bad task id" validation errors - Message updatedMessage = Message.builder(params.message()) - .taskId(taskId) - .build(); - paramsToUse = new MessageSendParams( - updatedMessage, - params.configuration(), - params.metadata()); - } else { - // TaskId matches, reuse original params to preserve Message object identity - paramsToUse = params; - } - - requestContext = requestContextBuilder.get() - .setParams(paramsToUse) - .setTask(task) - .setServerCallContext(context) - .build(); - } - // else: task is null and taskId matches - use the original requestContext - - return new MessageSendSetup(taskManager, task, requestContext); - } - - /** - * Log current thread and resource statistics for debugging. - * Uses dedicated {@link #THREAD_STATS_LOGGER} for independent logging control. - * Only logs when DEBUG level is enabled. Call this from debugger or add strategic - * calls during investigation. In production with INFO logging, this is a no-op. - *

- * Enable independently with: {@code logging.level.io.a2a.server.diagnostics.ThreadStats=DEBUG} - *

- */ - @SuppressWarnings("unused") // Used for debugging - private void logThreadStats(String label) { - // Early return if debug logging is not enabled to avoid overhead - if (!THREAD_STATS_LOGGER.isDebugEnabled()) { - return; - } - - ThreadGroup rootGroup = Thread.currentThread().getThreadGroup(); - while (rootGroup.getParent() != null) { - rootGroup = rootGroup.getParent(); - } - int activeThreads = rootGroup.activeCount(); - - // Count specific thread types - Thread[] threads = new Thread[activeThreads * 2]; - int count = rootGroup.enumerate(threads); - int eventConsumerThreads = 0; - int agentExecutorThreads = 0; - for (int i = 0; i < count; i++) { - if (threads[i] != null) { - String name = threads[i].getName(); - if (name.startsWith("a2a-event-consumer-")) { - eventConsumerThreads++; - } else if (name.startsWith("a2a-agent-executor-")) { - agentExecutorThreads++; - } - } - } - - THREAD_STATS_LOGGER.debug("=== THREAD STATS: {} ===", label); - THREAD_STATS_LOGGER.debug("Total active threads: {}", activeThreads); - THREAD_STATS_LOGGER.debug("EventConsumer threads: {}", eventConsumerThreads); - THREAD_STATS_LOGGER.debug("AgentExecutor threads: {}", agentExecutorThreads); - THREAD_STATS_LOGGER.debug("Running agents: {}", runningAgents.size()); - THREAD_STATS_LOGGER.debug("Queue manager active queues: {}", queueManager.getClass().getSimpleName()); - - // List running agents - if (!runningAgents.isEmpty()) { - THREAD_STATS_LOGGER.debug("Running agent tasks:"); - runningAgents.forEach((taskId, future) -> - THREAD_STATS_LOGGER.debug(" - Task {}: {}", taskId, future.isDone() ? "DONE" : "RUNNING") - ); - } - - THREAD_STATS_LOGGER.debug("=== END THREAD STATS ==="); - } - - /** - * Check if an event represents a final task state. - * - * @param eventKind the event to check - * @return true if the event represents a final state (COMPLETED, FAILED, CANCELED, REJECTED, UNKNOWN) - */ - private boolean isFinalEvent(EventKind eventKind) { - if (!(eventKind instanceof Event event)) { - return false; - } - if (event instanceof Task task) { - return task.status() != null && task.status().state() != null - && task.status().state().isFinal(); - } else if (event instanceof TaskStatusUpdateEvent statusUpdate) { - return statusUpdate.isFinal(); - } - return false; - } - - private record MessageSendSetup(TaskManager taskManager, @Nullable Task task, RequestContext requestContext) {} -} diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java b/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java deleted file mode 100644 index ff6139654..000000000 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.a2a.server.requesthandlers; - -import java.util.concurrent.Flow; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.ServerCallContext; -import io.a2a.spec.A2AError; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; - -public interface RequestHandler { - Task onGetTask( - TaskQueryParams params, - ServerCallContext context) throws A2AError; - - ListTasksResult onListTasks( - ListTasksParams params, - ServerCallContext context) throws A2AError; - - Task onCancelTask( - TaskIdParams params, - ServerCallContext context) throws A2AError; - - EventKind onMessageSend( - MessageSendParams params, - ServerCallContext context) throws A2AError; - - Flow.Publisher onMessageSendStream( - MessageSendParams params, - ServerCallContext context) throws A2AError; - - TaskPushNotificationConfig onCreateTaskPushNotificationConfig( - TaskPushNotificationConfig params, - ServerCallContext context) throws A2AError; - - TaskPushNotificationConfig onGetTaskPushNotificationConfig( - GetTaskPushNotificationConfigParams params, - ServerCallContext context) throws A2AError; - - Flow.Publisher onSubscribeToTask( - TaskIdParams params, - ServerCallContext context) throws A2AError; - - ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig( - ListTaskPushNotificationConfigParams params, - ServerCallContext context) throws A2AError; - - void onDeleteTaskPushNotificationConfig( - DeleteTaskPushNotificationConfigParams params, - ServerCallContext context) throws A2AError; -} diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/package-info.java b/server-common/src/main/java/io/a2a/server/requesthandlers/package-info.java deleted file mode 100644 index d4f3270f4..000000000 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.requesthandlers; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java b/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java deleted file mode 100644 index d300cbca2..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/AgentEmitter.java +++ /dev/null @@ -1,628 +0,0 @@ -package io.a2a.server.tasks; - -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.spec.A2AError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.jspecify.annotations.Nullable; - -/** - * Helper for emitting events from AgentExecutor implementations. - * - *

AgentEmitter provides a simplified API for agents to communicate with clients through - * the A2A protocol. It handles both task lifecycle management and direct message sending, - * automatically populating events with correct task and context IDs from the RequestContext. - * - *

Core Capabilities

- *
    - *
  • Task Lifecycle: {@link #submit()}, {@link #startWork()}, {@link #complete()}, - * {@link #fail()}, {@link #cancel()}, {@link #reject()}
  • - *
  • Message Sending: {@link #sendMessage(String)}, {@link #sendMessage(List)}, - * {@link #sendMessage(List, Map)}
  • - *
  • Artifact Streaming: {@link #addArtifact(List)}, {@link #addArtifact(List, String, String, Map)}
  • - *
  • Auth/Input Requirements: {@link #requiresAuth()}, {@link #requiresInput()}
  • - *
  • Custom Events: {@link #taskBuilder()}, {@link #messageBuilder()}, {@link #addTask(Task)}, {@link #emitEvent(Event)}
  • - *
- * - *

Usage Patterns

- * - *

Simple Message Response (No Task)

- *
{@code
- * public void execute(RequestContext context, AgentEmitter emitter) {
- *     String response = processRequest(context.getUserInput("\n"));
- *     emitter.sendMessage(response);
- * }
- * }
- * - *

Task Lifecycle with Artifacts

- *
{@code
- * public void execute(RequestContext context, AgentEmitter emitter) {
- *     if (context.getTask() == null) {
- *         emitter.submit();  // Create task in SUBMITTED state
- *     }
- *     emitter.startWork();  // Transition to WORKING
- *
- *     // Process and stream results
- *     List> results = doWork(context.getUserInput("\n"));
- *     emitter.addArtifact(results);
- *
- *     emitter.complete();  // Mark as COMPLETED
- * }
- * }
- * - *

Streaming Response (LLM)

- *
{@code
- * public void execute(RequestContext context, AgentEmitter emitter) {
- *     emitter.startWork();
- *
- *     for (String chunk : llmService.stream(context.getUserInput("\n"))) {
- *         emitter.addArtifact(List.of(new TextPart(chunk)));
- *     }
- *
- *     emitter.complete();
- * }
- * }
- * - *

Event ID Management

- * All emitted events are automatically populated with: - *
    - *
  • taskId: From RequestContext (may be null for message-only responses)
  • - *
  • contextId: From RequestContext
  • - *
  • messageId: Generated UUID for messages
  • - *
  • artifactId: Generated UUID for artifacts (unless explicitly provided)
  • - *
- * - * Events are validated by the EventQueue to ensure taskId correctness. - * - * @see io.a2a.server.agentexecution.AgentExecutor - * @see RequestContext - * @see EventQueue - * @since 1.0.0 - */ -public class AgentEmitter { - private final EventQueue eventQueue; - private final String taskId; - private final String contextId; - private final AtomicBoolean terminalStateReached = new AtomicBoolean(false); - - /** - * Creates a new AgentEmitter for the given request context and event queue. - * - * @param context the request context containing task and context IDs - * @param eventQueue the event queue for enqueueing events - */ - public AgentEmitter(RequestContext context, EventQueue eventQueue) { - this.eventQueue = eventQueue; - this.taskId = context.getTaskId(); - this.contextId = context.getContextId(); - } - - private void updateStatus(TaskState taskState) { - updateStatus(taskState, null, taskState.isFinal()); - } - - /** - * Updates the task status to the given state with an optional message. - * - * @param taskState the new task state - * @param message optional message to include with the status update - */ - public void updateStatus(TaskState taskState, @Nullable Message message) { - updateStatus(taskState, message, taskState.isFinal()); - } - - /** - * Updates the task status to the given state with an optional message and finality flag. - * - * @param state the new task state - * @param message optional message to include with the status update - * @param isFinal whether this is a final status (prevents further updates) - */ - private void updateStatus(TaskState state, @Nullable Message message, boolean isFinal) { - // Check terminal state first (fail fast) - if (terminalStateReached.get()) { - throw new IllegalStateException("Cannot update task status - terminal state already reached"); - } - - // For final states, atomically set the flag - if (isFinal) { - if (!terminalStateReached.compareAndSet(false, true)) { - throw new IllegalStateException("Cannot update task status - terminal state already reached"); - } - } - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId(contextId) - .status(new TaskStatus(state, message, null)) - .build(); - eventQueue.enqueueEvent(event); - } - - /** - * Returns the context ID for this emitter. - * - * @return the context ID, or null if not available - */ - public @Nullable String getContextId() { - return this.contextId; - } - - /** - * Returns the task ID for this emitter. - * - * @return the task ID, or null if no task is associated - */ - public @Nullable String getTaskId() { - return this.taskId; - } - - /** - * Adds an artifact with the given parts to the task. - * - * @param parts the parts to include in the artifact - */ - public void addArtifact(List> parts) { - addArtifact(parts, null, null, null); - } - - /** - * Adds an artifact with the given parts, artifact ID, name, and metadata. - * - * @param parts the parts to include in the artifact - * @param artifactId optional artifact ID (generated if null) - * @param name optional artifact name - * @param metadata optional metadata map - */ - public void addArtifact(List> parts, @Nullable String artifactId, @Nullable String name, @Nullable Map metadata) { - addArtifact(parts, artifactId, name, metadata, null, null); - } - - /** - * Adds an artifact with all optional parameters. - * - * @param parts the parts to include in the artifact - * @param artifactId optional artifact ID (generated if null) - * @param name optional artifact name - * @param metadata optional metadata map - * @param append whether to append to an existing artifact - * @param lastChunk whether this is the last chunk in a streaming sequence - */ - public void addArtifact(List> parts, @Nullable String artifactId, @Nullable String name, @Nullable Map metadata, - @Nullable Boolean append, @Nullable Boolean lastChunk) { - if (artifactId == null) { - artifactId = UUID.randomUUID().toString(); - } - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId(taskId) - .contextId(contextId) - .artifact( - Artifact.builder() - .artifactId(artifactId) - .name(name) - .parts(parts) - .metadata(metadata) - .build() - ) - .append(append) - .lastChunk(lastChunk) - .build(); - eventQueue.enqueueEvent(event); - } - - /** - * Marks the task as COMPLETED. - */ - public void complete() { - complete(null); - } - - /** - * Marks the task as COMPLETED with an optional message. - * - * @param message optional message to include with completion - */ - public void complete(@Nullable Message message) { - updateStatus(TaskState.TASK_STATE_COMPLETED, message); - } - - /** - * Marks the task as FAILED. - */ - public void fail() { - fail((Message) null); - } - - /** - * Marks the task as FAILED with an optional message. - * - * @param message optional message to include with failure - */ - public void fail(@Nullable Message message) { - updateStatus(TaskState.TASK_STATE_FAILED, message); - } - - /** - * Enqueues an A2A error event which will automatically transition the task to FAILED. - *

- * Use this when you need to fail the task with a specific A2A error (such as - * {@link io.a2a.spec.UnsupportedOperationError}, {@link io.a2a.spec.InvalidRequestError}, - * {@link io.a2a.spec.TaskNotFoundError}, etc.) that should be sent to the client. - *

- *

- * The error event is enqueued and the MainEventBusProcessor will automatically transition - * the task to FAILED state. This ensures thread-safe state transitions without race conditions, - * as the single-threaded MainEventBusProcessor handles all state updates. - *

- *

- * Error events are terminal (stop event consumption) and trigger automatic FAILED state transition. - * The error details are sent to the originating client only, while the FAILED status is replicated - * to all nodes in multi-instance deployments. - *

- *

Example usage: - *

{@code
-     * public void execute(RequestContext context, AgentEmitter emitter) {
-     *     if (!isSupported(context.getMessage())) {
-     *         emitter.fail(new UnsupportedOperationError("Feature not supported"));
-     *         return;
-     *     }
-     *     // ... normal processing
-     * }
-     * }
- * - * @param error the A2A error to enqueue and send to the client - * @since 1.0.0 - */ - public void fail(A2AError error) { - // Set terminal state flag BEFORE enqueueing error - // This prevents race conditions where agent calls fail(error) then complete() - if (!terminalStateReached.compareAndSet(false, true)) { - throw new IllegalStateException("Cannot update task status - terminal state already reached"); - } - - eventQueue.enqueueEvent(error); - // Status transition happens automatically in MainEventBusProcessor - // The error event is terminal and will trigger FAILED state transition - } - - /** - * Marks the task as SUBMITTED. - */ - public void submit() { - submit(null); - } - - /** - * Marks the task as SUBMITTED with an optional message. - * - * @param message optional message to include - */ - public void submit(@Nullable Message message) { - updateStatus(TaskState.TASK_STATE_SUBMITTED, message); - } - - /** - * Marks the task as WORKING (actively being processed). - */ - public void startWork() { - startWork(null); - } - - /** - * Marks the task as WORKING with an optional message. - * - * @param message optional message to include - */ - public void startWork(@Nullable Message message) { - updateStatus(TaskState.TASK_STATE_WORKING, message); - } - - /** - * Marks the task as CANCELED. - */ - public void cancel() { - cancel(null); - } - - /** - * Marks the task as CANCELED with an optional message. - * - * @param message optional message to include - */ - public void cancel(@Nullable Message message) { - updateStatus(TaskState.TASK_STATE_CANCELED, message); - } - - /** - * Marks the task as REJECTED. - */ - public void reject() { - reject(null); - } - - /** - * Marks the task as REJECTED with an optional message. - * - * @param message optional message to include - */ - public void reject(@Nullable Message message) { - updateStatus(TaskState.TASK_STATE_REJECTED, message); - } - - /** - * Marks the task as INPUT_REQUIRED, indicating the agent needs user input to continue. - */ - public void requiresInput() { - requiresInput(null, false); - } - - /** - * Marks the task as INPUT_REQUIRED with an optional message. - * - * @param message optional message to include - */ - public void requiresInput(@Nullable Message message) { - requiresInput(message, false); - } - - /** - * Marks the task as INPUT_REQUIRED with a finality flag. - * - * @param isFinal whether this is a final status (prevents further updates) - */ - public void requiresInput(boolean isFinal) { - requiresInput(null, isFinal); - } - - /** - * Marks the task as INPUT_REQUIRED with an optional message and finality flag. - * - * @param message optional message to include - * @param isFinal whether this is a final status (prevents further updates) - */ - public void requiresInput(@Nullable Message message, boolean isFinal) { - updateStatus(TaskState.TASK_STATE_INPUT_REQUIRED, message, isFinal); - } - - /** - * Marks the task as AUTH_REQUIRED, indicating the agent needs authentication to continue. - */ - public void requiresAuth() { - requiresAuth(null, false); - } - - /** - * Marks the task as AUTH_REQUIRED with an optional message. - * - * @param message optional message to include - */ - public void requiresAuth(@Nullable Message message) { - requiresAuth(message, false); - } - - /** - * Marks the task as AUTH_REQUIRED with a finality flag. - * - * @param isFinal whether this is a final status (prevents further updates) - */ - public void requiresAuth(boolean isFinal) { - requiresAuth(null, isFinal); - } - - /** - * Marks the task as AUTH_REQUIRED with an optional message and finality flag. - * - * @param message optional message to include - * @param isFinal whether this is a final status (prevents further updates) - */ - public void requiresAuth(@Nullable Message message, boolean isFinal) { - updateStatus(TaskState.TASK_STATE_AUTH_REQUIRED, message, isFinal); - } - - /** - * Creates a new agent message with the given parts and metadata. - * Pre-populates the message with agent role, task ID, context ID, and a generated message ID. - * - * @param parts the parts to include in the message - * @param metadata optional metadata to attach to the message - * @return a new Message object ready to be sent - */ - public Message newAgentMessage(List> parts, @Nullable Map metadata) { - return Message.builder() - .role(Message.Role.ROLE_AGENT) - .taskId(taskId) - .contextId(contextId) - .messageId(UUID.randomUUID().toString()) - .metadata(metadata) - .parts(parts) - .build(); - } - - /** - * Sends a simple text message to the client. - * Convenience method for agents that respond with plain text without creating a task. - * - * @param text the text content to send - */ - public void sendMessage(String text) { - sendMessage(List.of(new TextPart(text))); - } - - /** - * Sends a message with custom parts (text, images, etc.) to the client. - * Use this for rich responses that don't require task lifecycle management. - * - * @param parts the message parts to send - */ - public void sendMessage(List> parts) { - sendMessage(parts, null); - } - - /** - * Sends a message with parts and metadata to the client. - * Creates an agent message with the current task and context IDs (if available) - * and enqueues it to the event queue. - * - * @param parts the message parts to send - * @param metadata optional metadata to attach to the message - */ - public void sendMessage(List> parts, @Nullable Map metadata) { - Message message = newAgentMessage(parts, metadata); - eventQueue.enqueueEvent(message); - } - - /** - * Sends an existing Message object directly to the client. - *

- * Use this when you need to forward or echo an existing message without creating a new one. - * The message is enqueued as-is, preserving its messageId, metadata, and all other fields. - *

- *

- * Note: This is typically used for forwarding user messages or preserving specific - * message properties. For most cases, prefer {@link #sendMessage(String)} or - * {@link #sendMessage(List)} which create new agent messages with generated IDs. - *

- *

Example usage: - *

{@code
-     * public void execute(RequestContext context, AgentEmitter emitter) {
-     *     // Echo the user's message back
-     *     emitter.sendMessage(context.getMessage());
-     * }
-     * }
- * - * @param message the message to send to the client - * @since 1.0.0 - */ - public void sendMessage(Message message) { - eventQueue.enqueueEvent(message); - } - - /** - * Adds a custom Task object to be sent to the client. - *

- * Use this when you need to create a Task with specific fields (history, artifacts, etc.) - * that the convenience methods like {@link #submit()}, {@link #startWork()}, or - * {@link #complete()} don't provide. - *

- *

- * Typical usage pattern: Build a task with {@link #taskBuilder()}, customize it, - * then add it with this method. - *

- *

Example usage: - *

{@code
-     * public void execute(RequestContext context, AgentEmitter emitter) {
-     *     // Create a task with specific status and history
-     *     Task task = emitter.taskBuilder()
-     *         .status(new TaskStatus(TaskState.SUBMITTED))
-     *         .history(List.of(context.getMessage()))
-     *         .build();
-     *     emitter.addTask(task);
-     * }
-     * }
- * - * @param task the task to add - * @since 1.0.0 - */ - public void addTask(Task task) { - eventQueue.enqueueEvent(task); - } - - /** - * Emits a custom Event object to the client. - *

- * This is a general-purpose method for emitting any Event type. Most agents should use the - * convenience methods ({@link #sendMessage(String)}, {@link #addTask(Task)}, - * {@link #addArtifact(List)}, {@link #complete()}, etc.), but this method provides flexibility - * for agents that need to create and emit custom events using the event builders. - *

- *

Example usage: - *

{@code
-     * public void execute(RequestContext context, AgentEmitter emitter) {
-     *     // Create a custom TaskStatusUpdateEvent
-     *     TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder()
-     *         .taskId(context.getTaskId())
-     *         .contextId(context.getContextId())
-     *         .status(new TaskStatus(TaskState.WORKING))
-     *         .isFinal(false)
-     *         .build();
-     *     emitter.emitEvent(event);
-     * }
-     * }
- * - * @param event the event to emit - * @since 1.0.0 - */ - public void emitEvent(Event event) { - eventQueue.enqueueEvent(event); - } - - /** - * Creates a Task.Builder pre-populated with the correct task and context IDs. - * Agents can customize other Task fields (status, artifacts, etc.) before calling build(). - * - *

Example usage: - *

{@code
-     * Task task = emitter.taskBuilder()
-     *     .status(new TaskStatus(TaskState.WORKING))
-     *     .build();
-     * }
- * - * @return a Task.Builder with id and contextId already set - */ - public Task.Builder taskBuilder() { - return Task.builder() - .id(taskId) - .contextId(contextId); - } - - /** - * Creates a Message.Builder pre-populated with agent defaults. - * Sets taskId only if non-null (messages can exist independently of tasks). - * - *

Pre-populated fields: - *

    - *
  • taskId - set only if this AgentEmitter has a non-null taskId
  • - *
  • contextId - current context ID
  • - *
  • role - Message.Role.AGENT
  • - *
  • messageId - generated UUID
  • - *
- * - *

Example usage: - *

{@code
-     * Message msg = emitter.messageBuilder()
-     *     .parts(List.of(new TextPart("Hello")))
-     *     .metadata(Map.of("key", "value"))
-     *     .build();
-     * }
- * - * @return a Message.Builder with common agent fields already set - */ - public Message.Builder messageBuilder() { - Message.Builder builder = Message.builder() - .contextId(contextId) - .role(Message.Role.ROLE_AGENT) - .messageId(UUID.randomUUID().toString()); - - // Only set taskId if present (messages can exist without tasks) - if (taskId != null) { - builder.taskId(taskId); - } - - return builder; - } - -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java b/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java deleted file mode 100644 index 0d6bdcf3b..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java +++ /dev/null @@ -1,162 +0,0 @@ -package io.a2a.server.tasks; - -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; -import static io.a2a.common.A2AHeaders.X_A2A_NOTIFICATION_TOKEN; - -import io.a2a.spec.TaskPushNotificationConfig; -import jakarta.annotation.Nullable; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpClientFactory; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.Message; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -public class BasePushNotificationSender implements PushNotificationSender { - - private static final Logger LOGGER = LoggerFactory.getLogger(BasePushNotificationSender.class); - public static final int DEFAULT_PAGE_SIZE = 100; - - // Fields set by constructor injection cannot be final. We need a noargs constructor for - // Jakarta compatibility, and it seems that making fields set by constructor injection - // final, is not proxyable in all runtimes - private A2AHttpClient httpClient; - private PushNotificationConfigStore configStore; - - - /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. - */ - @SuppressWarnings("NullAway") - protected BasePushNotificationSender() { - // For CDI proxy creation - this.httpClient = null; - this.configStore = null; - } - - @Inject - public BasePushNotificationSender(PushNotificationConfigStore configStore) { - this.httpClient = A2AHttpClientFactory.create(); - this.configStore = configStore; - } - - public BasePushNotificationSender(PushNotificationConfigStore configStore, A2AHttpClient httpClient) { - this.configStore = configStore; - this.httpClient = httpClient; - } - - @Override - public void sendNotification(StreamingEventKind event) { - String taskId = extractTaskId(event); - if (taskId == null) { - LOGGER.warn("Cannot send push notification: event does not contain taskId"); - return; - } - - List configs = new ArrayList<>(); - String nextPageToken = null; - do { - ListTaskPushNotificationConfigResult pageResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId, - DEFAULT_PAGE_SIZE, nextPageToken == null ? "" : nextPageToken, "")); - if (!pageResult.configs().isEmpty()) { - configs.addAll(pageResult.configs()); - } - nextPageToken = pageResult.nextPageToken(); - } while (nextPageToken != null); - - List> dispatchResults = configs - .stream() - .map(pushConfig -> dispatch(event, pushConfig.config())) - .toList(); - CompletableFuture allFutures = CompletableFuture.allOf(dispatchResults.toArray(new CompletableFuture[0])); - CompletableFuture dispatchResult = allFutures.thenApply(v -> dispatchResults.stream() - .allMatch(CompletableFuture::join)); - try { - boolean allSent = dispatchResult.get(); - if (!allSent) { - LOGGER.warn("Some push notifications failed to send for taskId: " + taskId); - } - } catch (InterruptedException | ExecutionException e) { - LOGGER.warn("Some push notifications failed to send for taskId " + taskId + ": {}", e.getMessage(), e); - } - } - - /** - * Extracts the task ID from a StreamingEventKind event. - * - * @param event the streaming event - * @return the task ID, or null if not available - */ - protected @Nullable String extractTaskId(StreamingEventKind event) { - if (event instanceof Task task) { - return task.id(); - } - if (event instanceof Message message) { - return message.taskId(); - } - if (event instanceof TaskStatusUpdateEvent statusUpdate) { - return statusUpdate.taskId(); - } - if (event instanceof TaskArtifactUpdateEvent artifactUpdate) { - return artifactUpdate.taskId(); - } - throw new IllegalStateException("Unknown StreamingEventKind: " + event); - } - - private CompletableFuture dispatch(StreamingEventKind event, PushNotificationConfig pushInfo) { - return CompletableFuture.supplyAsync(() -> dispatchNotification(event, pushInfo)); - } - - private boolean dispatchNotification(StreamingEventKind event, PushNotificationConfig pushInfo) { - String url = pushInfo.url(); - String token = pushInfo.token(); - - A2AHttpClient.PostBuilder postBuilder = httpClient.createPost(); - if (token != null && !token.isBlank()) { - postBuilder.addHeader(X_A2A_NOTIFICATION_TOKEN, token); - } - - String body; - try { - // JsonUtil.toJson automatically wraps StreamingEventKind in StreamResponse format - // (task/message/statusUpdate/artifactUpdate) per A2A spec section 4.3.3 - body = JsonUtil.toJson(event); - } catch (Throwable throwable) { - LOGGER.error("Error serializing StreamingEventKind to JSON: {}", throwable.getMessage(), throwable); - return false; - } - - try { - postBuilder - .url(url) - .addHeader(CONTENT_TYPE, APPLICATION_JSON) - .body(body) - .post(); - } catch (IOException | InterruptedException e) { - LOGGER.debug("Error pushing data to " + url + ": {}", e.getMessage(), e); - return false; - } - return true; - } -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java b/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java deleted file mode 100644 index e67ae01eb..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java +++ /dev/null @@ -1,121 +0,0 @@ -package io.a2a.server.tasks; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.TaskPushNotificationConfig; - -/** - * In-memory implementation of the PushNotificationConfigStore interface. - * - * Stores push notification configurations in memory - */ -@ApplicationScoped -public class InMemoryPushNotificationConfigStore implements PushNotificationConfigStore { - - private final Map> pushNotificationInfos = Collections.synchronizedMap(new HashMap<>()); - - @Inject - public InMemoryPushNotificationConfigStore() { - } - - @Override - public PushNotificationConfig setInfo(String taskId, PushNotificationConfig notificationConfig) { - List notificationConfigList = pushNotificationInfos.getOrDefault(taskId, new ArrayList<>()); - PushNotificationConfig.Builder builder = PushNotificationConfig.builder(notificationConfig); - if (notificationConfig.id() == null || notificationConfig.id().isEmpty()) { - builder.id(taskId); - } - notificationConfig = builder.build(); - - Iterator notificationConfigIterator = notificationConfigList.iterator(); - while (notificationConfigIterator.hasNext()) { - PushNotificationConfig config = notificationConfigIterator.next(); - if (config.id() != null && config.id().equals(notificationConfig.id())) { - notificationConfigIterator.remove(); - break; - } - } - notificationConfigList.add(notificationConfig); - pushNotificationInfos.put(taskId, notificationConfigList); - return notificationConfig; - } - - @Override - public ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConfigParams params) { - List configs = pushNotificationInfos.get(params.id()); - if (configs == null) { - return new ListTaskPushNotificationConfigResult(Collections.emptyList()); - } - if (params.pageSize() <= 0) { - return new ListTaskPushNotificationConfigResult(convertPushNotificationConfig(configs, params), null); - } - if (params.pageToken() != null && !params.pageToken().isBlank()) { - //find first index - int index = findFirstIndex(configs, params.pageToken()); - if (index < configs.size()) { - configs = configs.subList(index, configs.size()); - } - } - if (configs.size() <= params.pageSize()) { - return new ListTaskPushNotificationConfigResult(convertPushNotificationConfig(configs, params), null); - } - String newToken = configs.get(params.pageSize()).id(); - return new ListTaskPushNotificationConfigResult(convertPushNotificationConfig(configs.subList(0, params.pageSize()), params), newToken); - } - - private int findFirstIndex(List configs, String id) { - //find first index - Iterator iter = configs.iterator(); - int index = 0; - while (iter.hasNext()) { - if (id.equals(iter.next().id())) { - return index; - } - index++; - } - return index; - } - - private List convertPushNotificationConfig(List pushNotificationConfigList, ListTaskPushNotificationConfigParams params) { - List taskPushNotificationConfigList = new ArrayList<>(pushNotificationConfigList.size()); - for (PushNotificationConfig pushNotificationConfig : pushNotificationConfigList) { - TaskPushNotificationConfig taskPushNotificationConfig = new TaskPushNotificationConfig(params.id(), pushNotificationConfig, params.tenant()); - taskPushNotificationConfigList.add(taskPushNotificationConfig); - } - return taskPushNotificationConfigList; - } - - @Override - public void deleteInfo(String taskId, String configId) { - if (configId == null) { - configId = taskId; - } - List notificationConfigList = pushNotificationInfos.get(taskId); - if (notificationConfigList == null || notificationConfigList.isEmpty()) { - return; - } - - Iterator notificationConfigIterator = notificationConfigList.iterator(); - while (notificationConfigIterator.hasNext()) { - PushNotificationConfig config = notificationConfigIterator.next(); - if (configId.equals(config.id())) { - notificationConfigIterator.remove(); - break; - } - } - if (notificationConfigList.isEmpty()) { - pushNotificationInfos.remove(taskId); - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java b/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java deleted file mode 100644 index 15f94d7e8..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java +++ /dev/null @@ -1,185 +0,0 @@ -package io.a2a.server.tasks; - -import java.util.Comparator; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import jakarta.enterprise.context.ApplicationScoped; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.Artifact; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.util.PageToken; -import io.a2a.spec.Task; -import org.jspecify.annotations.Nullable; - -/** - * In-memory implementation of {@link TaskStore} and {@link TaskStateProvider}. - *

- * This implementation uses a {@link ConcurrentHashMap} to store tasks in memory. - * Tasks are lost on application restart. For persistent storage, use a database-backed - * implementation such as the JPA TaskStore in the extras module. - *

- *

- * This is the default TaskStore used when no other implementation is provided. - *

- */ -@ApplicationScoped -public class InMemoryTaskStore implements TaskStore, TaskStateProvider { - - private final ConcurrentMap tasks = new ConcurrentHashMap<>(); - - @Override - public void save(Task task, boolean isReplicated) { - tasks.put(task.id(), task); - // InMemoryTaskStore doesn't fire TaskFinalizedEvent, so isReplicated is unused here - } - - @Override - public @Nullable Task get(String taskId) { - return tasks.get(taskId); - } - - @Override - public void delete(String taskId) { - tasks.remove(taskId); - } - - @Override - public ListTasksResult list(ListTasksParams params) { - // Filter and sort tasks in a single stream pipeline - List allFilteredTasks = tasks.values().stream() - .filter(task -> params.contextId() == null || params.contextId().equals(task.contextId())) - .filter(task -> params.status() == null || - (task.status() != null && params.status().equals(task.status().state()))) - .filter(task -> params.statusTimestampAfter() == null || - (task.status() != null && - task.status().timestamp() != null && - task.status().timestamp().toInstant().isAfter(params.statusTimestampAfter()))) - .sorted(Comparator.comparing( - (Task t) -> (t.status() != null && t.status().timestamp() != null) - // Truncate to milliseconds for consistency with pageToken precision - ? t.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS) - : null, - Comparator.nullsLast(Comparator.reverseOrder())) - .thenComparing(Task::id)) - .toList(); - - int totalSize = allFilteredTasks.size(); - - // Apply pagination - int pageSize = params.getEffectivePageSize(); - int startIndex = 0; - - // Handle page token using keyset pagination (format: "timestamp_millis:taskId") - // Use binary search to efficiently find the first task after the pageToken position (O(log N)) - PageToken pageToken = PageToken.fromString(params.pageToken()); - if (pageToken != null) { - java.time.Instant tokenTimestamp = pageToken.timestamp(); - String tokenId = pageToken.id(); - - // Binary search for first task where: timestamp < tokenTimestamp OR (timestamp == tokenTimestamp AND id > tokenId) - // Since list is sorted (timestamp DESC, id ASC), we search for the insertion point - int left = 0; - int right = allFilteredTasks.size(); - - while (left < right) { - int mid = left + (right - left) / 2; - Task task = allFilteredTasks.get(mid); - - java.time.Instant taskTimestamp = (task.status() != null && task.status().timestamp() != null) - ? task.status().timestamp().toInstant().truncatedTo(java.time.temporal.ChronoUnit.MILLIS) - : null; - - if (taskTimestamp == null) { - // Task with null timestamp is always "before" a token with a timestamp, as they are sorted last. - // So, we search in the right half. - left = mid + 1; - } else { - int timestampCompare = taskTimestamp.compareTo(tokenTimestamp); - - if (timestampCompare < 0 || (timestampCompare == 0 && task.id().compareTo(tokenId) > 0)) { - // This task is after the token, search left half - right = mid; - } else { - // This task is before or equal to token, search right half - left = mid + 1; - } - } - } - startIndex = left; - } - - // Get the page of tasks - int endIndex = Math.min(startIndex + pageSize, allFilteredTasks.size()); - List pageTasks = allFilteredTasks.subList(startIndex, endIndex); - - // Determine next page token (format: "timestamp_millis:taskId") - String nextPageToken = null; - if (endIndex < allFilteredTasks.size()) { - Task lastTask = allFilteredTasks.get(endIndex - 1); - // All tasks have timestamps (TaskStatus canonical constructor ensures this) - java.time.Instant timestamp = lastTask.status().timestamp().toInstant(); - nextPageToken = new PageToken(timestamp, lastTask.id()).toString(); - } - - // Transform tasks: limit history and optionally remove artifacts - int historyLength = params.getEffectiveHistoryLength(); - boolean includeArtifacts = params.shouldIncludeArtifacts(); - - List transformedTasks = pageTasks.stream() - .map(task -> transformTask(task, historyLength, includeArtifacts)) - .toList(); - - return new ListTasksResult(transformedTasks, totalSize, transformedTasks.size(), nextPageToken); - } - - private Task transformTask(Task task, int historyLength, boolean includeArtifacts) { - // Limit history if needed (keep most recent N messages) - List history = task.history(); - if (historyLength == 0) { - // When historyLength is 0, return empty history - history = List.of(); - } else if (historyLength > 0 && history != null && history.size() > historyLength) { - history = history.subList(history.size() - historyLength, history.size()); - } - - // Remove artifacts if not requested - List artifacts = includeArtifacts ? task.artifacts() : List.of(); - - // If no transformation needed, return original task - if (history == task.history() && artifacts == task.artifacts()) { - return task; - } - - // Build new task with transformed data - return Task.builder(task) - .artifacts(artifacts) - .history(history) - .build(); - } - - @Override - public boolean isTaskActive(String taskId) { - Task task = tasks.get(taskId); - if (task == null) { - return false; - } - // Task is active if not in final state - return task.status() == null || task.status().state() == null || !task.status().state().isFinal(); - } - - @Override - public boolean isTaskFinalized(String taskId) { - Task task = tasks.get(taskId); - if (task == null) { - return false; - } - // Task is finalized if in final state (ignores grace period) - return task.status() != null - && task.status().state() != null - && task.status().state().isFinal(); - } -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java deleted file mode 100644 index 828b066a6..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java +++ /dev/null @@ -1,123 +0,0 @@ -package io.a2a.server.tasks; - -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; - -/** - * Interface for storing and retrieving push notification configurations for tasks. - *

- * Push notification configurations specify where and how to deliver task state updates - * to external systems (webhook URLs, authentication headers, etc.). A task can have - * multiple push notification configurations for different endpoints or use cases. - *

- * - *

Configuration ID Semantics

- * Each push notification config has an ID: - *
    - *
  • If not provided in {@link PushNotificationConfig}, defaults to the task ID
  • - *
  • Multiple configs per task require unique IDs (e.g., "webhook-1", "webhook-2")
  • - *
  • Used for retrieval and deletion of specific configurations
  • - *
- * - *

Pagination Support

- * {@link #getInfo(ListTaskPushNotificationConfigParams)} supports pagination for tasks - * with many push notification configurations: - *
    - *
  • pageSize: Maximum number of configs to return (0 = unlimited)
  • - *
  • pageToken: Continuation token from previous response
  • - *
  • Returns {@link ListTaskPushNotificationConfigResult} with configs and next page token
  • - *
- * - *

Default Implementation

- * {@link InMemoryPushNotificationConfigStore}: - *
    - *
  • Stores configs in {@link java.util.concurrent.ConcurrentHashMap}
  • - *
  • Thread-safe for concurrent operations
  • - *
  • Configs lost on application restart
  • - *
- * - *

Alternative Implementations

- *
    - *
  • extras/push-notification-config-store-database-jpa: Database persistence with JPA
  • - *
- * Database implementations survive restarts and enable config sharing across server instances. - * - *

CDI Extension Pattern

- *
{@code
- * @ApplicationScoped
- * @Alternative
- * @Priority(50)
- * public class JpaDatabasePushNotificationConfigStore implements PushNotificationConfigStore {
- *     @PersistenceContext
- *     EntityManager em;
- *
- *     @Transactional
- *     public PushNotificationConfig setInfo(String taskId, PushNotificationConfig config) {
- *         // JPA persistence logic
- *     }
- * }
- * }
- * - *

Thread Safety

- * Implementations must be thread-safe. Multiple threads may call methods concurrently - * for the same or different tasks. - * - * @see PushNotificationSender - * @see InMemoryPushNotificationConfigStore - * @see io.a2a.spec.PushNotificationConfig - */ -public interface PushNotificationConfigStore { - - /** - * Sets or updates the push notification configuration for a task. - *

- * If {@code notificationConfig.id()} is null or empty, it's set to the task ID. - * If a config with the same ID already exists for this task, it's replaced. - *

- * - * @param taskId the task ID - * @param notificationConfig the push notification configuration - * @return the potentially updated configuration (with ID set if it was null) - */ - PushNotificationConfig setInfo(String taskId, PushNotificationConfig notificationConfig); - - /** - * Retrieves push notification configurations for a task with pagination support. - *

- * Returns all configs if {@code params.pageSize()} is 0. Otherwise, returns up to - * {@code pageSize} configs and a continuation token for the next page. - *

- * Pagination Example: - *

{@code
-     * // First page
-     * ListTaskPushNotificationConfigParams params =
-     *     new ListTaskPushNotificationConfigParams(taskId, 10, null, tenant);
-     * ListTaskPushNotificationConfigResult result = store.getInfo(params);
-     *
-     * // Next page
-     * if (result.nextPageToken() != null) {
-     *     params = new ListTaskPushNotificationConfigParams(
-     *         taskId, 10, result.nextPageToken(), tenant);
-     *     result = store.getInfo(params);
-     * }
-     * }
- * - * @param params the query parameters including task ID, page size, and page token - * @return the configurations for this task (empty list if none found) - */ - ListTaskPushNotificationConfigResult getInfo(ListTaskPushNotificationConfigParams params); - - /** - * Deletes a push notification configuration for a task. - *

- * If {@code configId} is null, it defaults to the task ID (deletes the default config). - * If no config exists with the given ID, this method returns normally (idempotent). - *

- * - * @param taskId the task ID - * @param configId the push notification configuration ID (null = use task ID) - */ - void deleteInfo(String taskId, String configId); - -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java deleted file mode 100644 index f8b7b018d..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationSender.java +++ /dev/null @@ -1,109 +0,0 @@ -package io.a2a.server.tasks; - -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; - -/** - * Interface for delivering push notifications containing task state updates to external systems. - *

- * Push notifications enable asynchronous, out-of-band communication of task progress to - * configured webhook URLs or messaging systems. This allows clients to receive updates - * without maintaining persistent connections or polling. - *

- * - *

Invocation Context

- * Called by {@link io.a2a.server.requesthandlers.DefaultRequestHandler} after: - *
    - *
  • Task events are persisted to {@link TaskStore}
  • - *
  • Events are returned/streamed to the requesting client
  • - *
  • For streaming: after each event emission to the client
  • - *
  • For blocking: after the initial response is returned
  • - *
- *

- * Push notifications are always sent AFTER the task state is persisted and the client - * has received the event, ensuring consistency. - *

- * - *

Default Implementation

- * {@link BasePushNotificationSender} provides HTTP webhook delivery: - *
    - *
  • Retrieves webhook URLs from {@link PushNotificationConfigStore}
  • - *
  • Wraps events in StreamResponse format (per A2A spec section 4.3.3)
  • - *
  • Sends HTTP POST requests with StreamResponse JSON payload
  • - *
  • Logs errors but doesn't fail the request
  • - *
- * - *

Alternative Implementations

- * Custom implementations can deliver notifications via: - *
    - *
  • Kafka topics for event streaming
  • - *
  • AWS SNS/SQS for cloud messaging
  • - *
  • WebSockets for real-time browser updates
  • - *
  • Custom messaging protocols
  • - *
- * - *

CDI Extension Pattern

- *
{@code
- * @ApplicationScoped
- * @Alternative
- * @Priority(100)
- * public class KafkaPushNotificationSender implements PushNotificationSender {
- *     @Inject
- *     KafkaProducer producer;
- *
- *     @Override
- *     public void sendNotification(StreamingEventKind event) {
- *         String taskId = extractTaskId(event);
- *         producer.send("task-updates", taskId, event);
- *     }
- * }
- * }
- * - *

Error Handling

- * Implementations should handle errors gracefully: - *
    - *
  • Log failures but don't throw exceptions (notifications are best-effort)
  • - *
  • Consider retry logic for transient failures
  • - *
  • Don't block on network I/O - execute asynchronously if needed
  • - *
  • Circuit breaker patterns for repeatedly failing endpoints
  • - *
- * Throwing exceptions from this method will not fail the client request, but will - * be logged as errors. - * - *

Thread Safety

- * May be called from multiple threads concurrently for different tasks. - * Implementations must be thread-safe. - * - * @see PushNotificationConfigStore - * @see BasePushNotificationSender - * @see io.a2a.spec.PushNotificationConfig - */ -public interface PushNotificationSender { - - /** - * Sends a push notification containing a streaming event. - *

- * Called after the event has been persisted to {@link TaskStore}. The event is wrapped - * in a StreamResponse format (per A2A spec section 4.3.3) with the appropriate oneof - * field set (task, message, statusUpdate, or artifactUpdate). - *

- *

- * Retrieve push notification URLs or messaging configurations from - * {@link PushNotificationConfigStore} using the task ID extracted from the event. - *

- * Supported event types: - *
    - *
  • {@link Task} - wrapped in StreamResponse.task
  • - *
  • {@link io.a2a.spec.Message} - wrapped in StreamResponse.message
  • - *
  • {@link io.a2a.spec.TaskStatusUpdateEvent} - wrapped in StreamResponse.statusUpdate
  • - *
  • {@link io.a2a.spec.TaskArtifactUpdateEvent} - wrapped in StreamResponse.artifactUpdate
  • - *
- *

- * Error Handling: Log errors but don't throw exceptions. Notifications are - * best-effort and should not fail the primary request. - *

- * - * @param event the streaming event to send (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) - */ - void sendNotification(StreamingEventKind event); -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java b/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java deleted file mode 100644 index 06c689eb2..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java +++ /dev/null @@ -1,313 +0,0 @@ -package io.a2a.server.tasks; - -import static io.a2a.server.util.async.AsyncUtils.consumer; -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; -import static io.a2a.server.util.async.AsyncUtils.processor; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import io.a2a.server.events.EventConsumer; -import io.a2a.server.events.EventQueueItem; -import io.a2a.spec.A2AError; -import io.a2a.spec.Event; -import io.a2a.spec.EventKind; -import io.a2a.spec.InternalError; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ResultAggregator { - private static final Logger LOGGER = LoggerFactory.getLogger(ResultAggregator.class); - - private final TaskManager taskManager; - private final Executor executor; - private final Executor eventConsumerExecutor; - private volatile @Nullable Message message; - - public ResultAggregator(TaskManager taskManager, @Nullable Message message, Executor executor, Executor eventConsumerExecutor) { - this.taskManager = taskManager; - this.message = message; - this.executor = executor; - this.eventConsumerExecutor = eventConsumerExecutor; - } - - public @Nullable EventKind getCurrentResult() { - if (message != null) { - return message; - } - return taskManager.getTask(); - } - - public Flow.Publisher consumeAndEmit(EventConsumer consumer) { - Flow.Publisher allItems = consumer.consumeAll(); - - // Just stream events - no persistence needed - // TaskStore update moved to MainEventBusProcessor - Flow.Publisher processed = processor(createTubeConfig(), allItems, (errorConsumer, item) -> { - // Continue processing and emit all events - return true; - }); - - // Wrap the publisher to ensure subscription happens on eventConsumerExecutor - // This prevents EventConsumer polling loop from running on AgentExecutor threads - // which caused thread accumulation when those threads didn't timeout - return new Flow.Publisher() { - @Override - public void subscribe(Flow.Subscriber subscriber) { - // Submit subscription to eventConsumerExecutor to isolate polling work - eventConsumerExecutor.execute(() -> processed.subscribe(subscriber)); - } - }; - } - - public EventKind consumeAll(EventConsumer consumer) throws A2AError { - AtomicReference returnedEvent = new AtomicReference<>(); - Flow.Publisher allItems = consumer.consumeAll(); - AtomicReference error = new AtomicReference<>(); - consumer( - createTubeConfig(), - allItems, - (item) -> { - Event event = item.getEvent(); - if (event instanceof Message msg) { - message = msg; - if (returnedEvent.get() == null) { - returnedEvent.set(msg); - return false; - } - } - // TaskStore update moved to MainEventBusProcessor - return true; - }, - error::set); - - Throwable err = error.get(); - if (err != null) { - Utils.rethrow(err); - } - - EventKind result = returnedEvent.get(); - if (result != null) { - return result; - } - Task task = taskManager.getTask(); - if (task == null) { - throw new io.a2a.spec.InternalError("No task or message available after consuming all events"); - } - return task; - } - - public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, boolean blocking) throws A2AError { - Flow.Publisher allItems = consumer.consumeAll(); - AtomicReference message = new AtomicReference<>(); - AtomicReference capturedTask = new AtomicReference<>(); // Capture Task events - AtomicBoolean interrupted = new AtomicBoolean(false); - AtomicReference errorRef = new AtomicReference<>(); - CompletableFuture completionFuture = new CompletableFuture<>(); - // Separate future for tracking background consumption completion - CompletableFuture consumptionCompletionFuture = new CompletableFuture<>(); - // Latch to ensure EventConsumer starts polling before we wait on completionFuture - java.util.concurrent.CountDownLatch pollingStarted = new java.util.concurrent.CountDownLatch(1); - - // CRITICAL: The subscription itself must run on a background thread to avoid blocking - // the Vert.x worker thread. EventConsumer.consumeAll() starts a polling loop that - // blocks in dequeueEventItem(), so we must subscribe from a background thread. - // Use the dedicated @EventConsumerExecutor (cached thread pool) which creates threads - // on demand for I/O-bound polling. Using the @Internal executor caused deadlock when - // pool exhausted (100+ concurrent queues but maxPoolSize=50). - CompletableFuture.runAsync(() -> { - // Signal that polling is about to start - pollingStarted.countDown(); - consumer( - createTubeConfig(), - allItems, - (item) -> { - Event event = item.getEvent(); - - // Handle Throwable events - if (event instanceof Throwable t) { - errorRef.set(t); - completionFuture.completeExceptionally(t); - return false; - } - - // Handle Message events - if (event instanceof Message msg) { - ResultAggregator.this.message = msg; - message.set(msg); - completionFuture.complete(null); - return false; - } - - // Capture Task events (especially for new tasks where taskManager.getTask() would return null) - // We capture the LATEST task to ensure we get the most up-to-date state - if (event instanceof Task t) { - Task previousTask = capturedTask.get(); - capturedTask.set(t); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Captured Task event: id={}, state={} (previous: {})", - t.id(), t.status().state(), - previousTask != null ? previousTask.id() + "/" + previousTask.status().state() : "none"); - } - } - - // TaskStore update moved to MainEventBusProcessor - - // Determine interrupt behavior - boolean shouldInterrupt = false; - boolean isFinalEvent = (event instanceof Task task && task.status().state().isFinal()) - || (event instanceof TaskStatusUpdateEvent tsue && tsue.isFinal()) - || (event instanceof A2AError); // A2AError events are terminal - boolean isAuthRequired = (event instanceof Task task && task.status().state() == TaskState.TASK_STATE_AUTH_REQUIRED) - || (event instanceof TaskStatusUpdateEvent tsue && tsue.status().state() == TaskState.TASK_STATE_AUTH_REQUIRED); - - LOGGER.debug("ResultAggregator: Evaluating interrupt (blocking={}, isFinal={}, isAuth={}, eventType={})", - blocking, isFinalEvent, isAuthRequired, event.getClass().getSimpleName()); - - // Always interrupt on auth_required, as it needs external action. - if (isAuthRequired) { - // auth-required is a special state: the message should be - // escalated back to the caller, but the agent is expected to - // continue producing events once the authorization is received - // out-of-band. This is in contrast to input-required, where a - // new request is expected in order for the agent to make progress, - // so the agent should exit. - shouldInterrupt = true; - LOGGER.debug("ResultAggregator: Setting shouldInterrupt=true (AUTH_REQUIRED)"); - } - else if (!blocking) { - // For non-blocking calls, interrupt as soon as a task is available. - shouldInterrupt = true; - LOGGER.debug("ResultAggregator: Setting shouldInterrupt=true (non-blocking)"); - } - else if (blocking) { - // For blocking calls: Interrupt to free Vert.x thread, but continue in background - // Python's async consumption doesn't block threads, but Java's does - // So we interrupt to return quickly, then rely on background consumption - shouldInterrupt = true; - LOGGER.debug("ResultAggregator: Setting shouldInterrupt=true (blocking, isFinal={})", isFinalEvent); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Blocking call for task {}: {} event, returning with background consumption", - taskIdForLogging(), isFinalEvent ? "final" : "non-final"); - } - } - - if (shouldInterrupt) { - LOGGER.debug("ResultAggregator: Interrupting consumption (setting interrupted=true)"); - // Complete the future to unblock the main thread - interrupted.set(true); - completionFuture.complete(null); - - // For blocking calls, DON'T complete consumptionCompletionFuture here. - // Let it complete naturally when subscription finishes (onComplete callback below). - // This ensures all events are fully processed before cleanup. - // - // For non-blocking and auth-required calls, complete immediately to allow - // cleanup to proceed while consumption continues in background. - if (!blocking) { - consumptionCompletionFuture.complete(null); - } - // else: blocking calls wait for actual consumption completion in onComplete - - // Continue consuming in background - keep requesting events - // Note: continueInBackground is always true when shouldInterrupt is true - // (auth-required, non-blocking, or blocking all set it to true) - if (LOGGER.isDebugEnabled()) { - String reason = isAuthRequired ? "auth-required" : (blocking ? "blocking" : "non-blocking"); - LOGGER.debug("Task {}: Continuing background consumption (reason: {})", taskIdForLogging(), reason); - } - return true; - } - - // Continue processing - return true; - }, - throwable -> { - // Handle onError and onComplete - if (throwable != null) { - errorRef.set(throwable); - completionFuture.completeExceptionally(throwable); - consumptionCompletionFuture.completeExceptionally(throwable); - } else { - // onComplete - subscription finished normally - completionFuture.complete(null); - consumptionCompletionFuture.complete(null); - } - } - ); - }, eventConsumerExecutor); - - // Wait for EventConsumer to start polling before we wait for events - // This prevents race where agent enqueues events before EventConsumer starts - try { - pollingStarted.await(5, java.util.concurrent.TimeUnit.SECONDS); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new io.a2a.spec.InternalError("Interrupted waiting for EventConsumer to start"); - } - - // Wait for completion or interruption - try { - completionFuture.join(); - } catch (CompletionException e) { - // CompletionException wraps the actual exception - Throwable cause = e.getCause(); - if (cause != null) { - Utils.rethrow(cause); - } else { - throw e; - } - } - - // Note: For blocking calls that were interrupted, the wait logic has been moved - // to DefaultRequestHandler.onMessageSend() to avoid blocking Vert.x worker threads. - // Queue lifecycle is managed by DefaultRequestHandler.cleanupProducer() - - Throwable error = errorRef.get(); - if (error != null) { - Utils.rethrow(error); - } - - // Return Message if captured, otherwise Task if captured, otherwise fetch from TaskStore - EventKind eventKind = message.get(); - if (eventKind == null) { - eventKind = capturedTask.get(); - if (LOGGER.isDebugEnabled() && eventKind instanceof Task t) { - LOGGER.debug("Returning capturedTask: id={}, state={}", t.id(), t.status().state()); - } - } - if (eventKind == null) { - eventKind = taskManager.getTask(); - if (LOGGER.isDebugEnabled() && eventKind instanceof Task t) { - LOGGER.debug("Returning task from TaskStore: id={}, state={}", t.id(), t.status().state()); - } - } - if (eventKind == null) { - throw new InternalError("Could not find a Task/Message for " + taskManager.getTaskId()); - } - - return new EventTypeAndInterrupt( - eventKind, - interrupted.get(), - consumptionCompletionFuture); - } - - private String taskIdForLogging() { - Task task = taskManager.getTask(); - return task != null ? task.id() : "unknown"; - } - - public record EventTypeAndInterrupt(EventKind eventType, boolean interrupted, CompletableFuture consumptionFuture) { - - } -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java b/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java deleted file mode 100644 index bba80bf53..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java +++ /dev/null @@ -1,224 +0,0 @@ -package io.a2a.server.tasks; - -import static io.a2a.spec.TaskState.TASK_STATE_FAILED; -import static io.a2a.spec.TaskState.TASK_STATE_SUBMITTED; -import static io.a2a.util.Assert.checkNotNullParam; -import static io.a2a.util.Utils.appendArtifactToTask; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TaskManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(TaskManager.class); - - private volatile @Nullable String taskId; - private volatile @Nullable String contextId; - private final TaskStore taskStore; - private final @Nullable Message initialMessage; - private volatile @Nullable Task currentTask; - - public TaskManager(@Nullable String taskId, @Nullable String contextId, TaskStore taskStore, @Nullable Message initialMessage) { - checkNotNullParam("taskStore", taskStore); - this.taskId = taskId; - this.contextId = contextId; - this.taskStore = taskStore; - this.initialMessage = initialMessage; - } - - @Nullable String getTaskId() { - return taskId; - } - - @Nullable String getContextId() { - return contextId; - } - - public @Nullable Task getTask() { - if (taskId == null) { - return null; - } - if (currentTask != null) { - return currentTask; - } - currentTask = taskStore.get(taskId); - return currentTask; - } - - boolean saveTaskEvent(Task task, boolean isReplicated) throws A2AServerException { - checkIdsAndUpdateIfNecessary(task.id(), task.contextId()); - Task savedTask = saveTask(task, isReplicated); - return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); - } - - boolean saveTaskEvent(TaskStatusUpdateEvent event, boolean isReplicated) throws A2AServerException { - checkIdsAndUpdateIfNecessary(event.taskId(), event.contextId()); - Task task = ensureTask(event.taskId(), event.contextId()); - - - Task.Builder builder = Task.builder(task) - .status(event.status()); - - if (task.status().message() != null) { - List newHistory = task.history() == null ? new ArrayList<>() : new ArrayList<>(task.history()); - newHistory.add(task.status().message()); - builder.history(newHistory); - } - - // Handle metadata from the event - if (event.metadata() != null) { - Map metadata = task.metadata() == null ? new HashMap<>() : new HashMap<>(task.metadata()); - metadata.putAll(event.metadata()); - builder.metadata(metadata); - } - - task = builder.build(); - Task savedTask = saveTask(task, isReplicated); - return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); - } - - boolean saveTaskEvent(TaskArtifactUpdateEvent event, boolean isReplicated) throws A2AServerException { - checkIdsAndUpdateIfNecessary(event.taskId(), event.contextId()); - Task task = ensureTask(event.taskId(), event.contextId()); - // taskId is guaranteed to be non-null after checkIdsAndUpdateIfNecessary - String nonNullTaskId = taskId; - if (nonNullTaskId == null) { - throw new IllegalStateException("taskId should not be null after checkIdsAndUpdateIfNecessary"); - } - task = appendArtifactToTask(task, event, nonNullTaskId); - Task savedTask = saveTask(task, isReplicated); - return savedTask.status() != null && savedTask.status().state() != null && savedTask.status().state().isFinal(); - } - - public boolean process(Event event, boolean isReplicated) throws A2AServerException { - boolean isFinal = false; - if (event instanceof Task task) { - isFinal = saveTaskEvent(task, isReplicated); - } else if (event instanceof TaskStatusUpdateEvent taskStatusUpdateEvent) { - isFinal = saveTaskEvent(taskStatusUpdateEvent, isReplicated); - } else if (event instanceof TaskArtifactUpdateEvent taskArtifactUpdateEvent) { - isFinal = saveTaskEvent(taskArtifactUpdateEvent, isReplicated); - } else if (event instanceof A2AError) { - // A2AError events trigger automatic transition to FAILED state - // Error details are NOT persisted in TaskStore (client-specific) - // Only the FAILED status is persisted and replicated across nodes - - // A2AError events don't have taskId/contextId fields, so we need to ensure - // we have these from the existing task or TaskManager state - if (taskId == null) { - // No task context - A2AError event will be distributed to clients but no state update - LOGGER.debug("A2AError event without task context - skipping state update"); - return true; // Return true (is final) to stop event consumption - } - - // Ensure we have contextId - get from existing task if not set - String errorContextId = contextId; - if (errorContextId == null) { - Task existingTask = getTask(); - if (existingTask != null) { - errorContextId = existingTask.contextId(); - } - } - - // Only create status update if we have contextId - if (errorContextId != null) { - LOGGER.debug("A2AError event detected, transitioning task {} to FAILED", taskId); - TaskStatusUpdateEvent failedEvent = TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId(errorContextId) - .status(new TaskStatus(TASK_STATE_FAILED)) - .build(); - isFinal = saveTaskEvent(failedEvent, isReplicated); - } else { - // Can't update status without contextId, but error is still terminal - LOGGER.debug("A2AError event for task {} without contextId - skipping state update", taskId); - isFinal = true; - } - } - return isFinal; - } - - public Task updateWithMessage(Message message, Task task) { - List history = new ArrayList<>(task.history()); - - TaskStatus status = task.status(); - if (status.message() != null) { - history.add(status.message()); - status = new TaskStatus(status.state(), null, status.timestamp()); - } - history.add(message); - task = Task.builder(task) - .status(status) - .history(history) - .build(); - saveTask(task, false); // Local operation, not replicated - return task; - } - - private void checkIdsAndUpdateIfNecessary(String eventTaskId, String eventContextId) throws A2AServerException { - if (taskId != null && !eventTaskId.equals(taskId)) { - throw new A2AServerException( - "Invalid task id", - new InternalError(String.format("Task event has taskId %s but TaskManager has %s", eventTaskId, taskId))); - } - if (taskId == null) { - taskId = eventTaskId; - } - if (contextId == null) { - contextId = eventContextId; - } - } - - private Task ensureTask(String eventTaskId, String eventContextId) { - Task task = currentTask; - if (task != null) { - return task; - } - // taskId may be null here, but get() accepts @Nullable - String currentTaskId = taskId; - if (currentTaskId != null) { - task = taskStore.get(currentTaskId); - } - if (task == null) { - task = createTask(eventTaskId, eventContextId); - saveTask(task, false); // Local operation, not replicated - } - return task; - } - - private Task createTask(String taskId, String contextId) { - List history = initialMessage != null ? List.of(initialMessage) : Collections.emptyList(); - return Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TASK_STATE_SUBMITTED)) - .history(history) - .build(); - } - - private Task saveTask(Task task, boolean isReplicated) { - taskStore.save(task, isReplicated); - if (taskId == null) { - taskId = task.id(); - contextId = task.contextId(); - } - currentTask = task; - return currentTask; - } -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskStateProvider.java b/server-common/src/main/java/io/a2a/server/tasks/TaskStateProvider.java deleted file mode 100644 index 837befa48..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskStateProvider.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.a2a.server.tasks; - -/** - * Provider interface for determining the active state of a task. - *

- * This interface decouples the queue lifecycle management from the task state persistence layer. - * Implementations should check the authoritative task state to determine whether a task is - * considered "active" for queue management purposes. - *

- *

- * A task is typically considered active if: - *

- *
    - *
  • Its state is not final (e.g., not COMPLETED, CANCELED, FAILED, etc.), OR
  • - *
  • Its state is final but it was finalized recently (within a configurable grace period)
  • - *
- *

- * The grace period mechanism handles race conditions in both replicated and non-replicated environments - * where events may be in-flight when a task finalizes. - *

- */ -public interface TaskStateProvider { - - /** - * Determines whether a task is considered active for queue management purposes. - *

- * This method includes the grace period in its check. A task is considered active if: - *

- *
    - *
  • Its state is not final, OR
  • - *
  • Its state is final but finalized within the grace period (now < finalizedAt + gracePeriod)
  • - *
- *

- * This method is used to decide whether to process late-arriving events. - *

- * - * @param taskId the ID of the task to check - * @return {@code true} if the task is active (or recently finalized within grace period), - * {@code false} otherwise - */ - boolean isTaskActive(String taskId); - - /** - * Determines whether a task is in a final state, ignoring the grace period. - *

- * This method performs an immediate check: returns {@code true} only if the task - * is in a final state (COMPLETED, CANCELED, FAILED, etc.), regardless of when - * it was finalized. - *

- *

- * This method is used by cleanup callbacks and MainQueue closing logic to decide whether - * a queue can be closed and removed. By ignoring the grace period, it ensures responsive - * cleanup while late in-flight events are still handled by the grace period mechanism - * for {@code isTaskActive}. - *

- * - * @param taskId the ID of the task to check - * @return {@code true} if the task is in a final state (ignoring grace period), - * {@code false} otherwise - */ - boolean isTaskFinalized(String taskId); -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java b/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java deleted file mode 100644 index 3df903f77..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java +++ /dev/null @@ -1,131 +0,0 @@ -package io.a2a.server.tasks; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Task; -import org.jspecify.annotations.Nullable; - -/** - * Storage interface for managing task persistence across the task lifecycle. - *

- * TaskStore is responsible for persisting task state including status updates, artifacts, - * message history, and metadata. It's called by {@link io.a2a.server.requesthandlers.DefaultRequestHandler} - * and {@link TaskManager} to save task state as agents process requests and generate events. - *

- * - *

Persistence Guarantees

- * Tasks are persisted: - *
    - *
  • After each status update event (SUBMITTED, WORKING, COMPLETED, etc.)
  • - *
  • After each artifact is added
  • - *
  • Before events are distributed to clients (ensures consistency)
  • - *
  • Before push notifications are sent
  • - *
- * Persistence happens synchronously before responses are returned, ensuring clients - * always see committed state. - * - *

Default Implementation

- * {@link InMemoryTaskStore}: - *
    - *
  • Stores tasks in {@link java.util.concurrent.ConcurrentHashMap}
  • - *
  • Also implements {@link TaskStateProvider} for queue lifecycle decisions
  • - *
  • Thread-safe for concurrent operations
  • - *
  • Tasks lost on application restart
  • - *
- * - *

Alternative Implementations

- *
    - *
  • extras/task-store-database-jpa: {@code JpaDatabaseTaskStore} with PostgreSQL/MySQL persistence
  • - *
- * Database implementations: - *
    - *
  • Survive application restarts
  • - *
  • Enable task sharing across server instances
  • - *
  • Typically also implement {@link TaskStateProvider} for integrated state queries
  • - *
  • Support transaction boundaries for consistency
  • - *
- * - *

Relationship to TaskStateProvider

- * Many TaskStore implementations also implement {@link TaskStateProvider} to provide - * queue lifecycle management with task state information: - *
{@code
- * @ApplicationScoped
- * public class InMemoryTaskStore implements TaskStore, TaskStateProvider {
- *     // Provides both persistence and state queries
- *     public boolean isTaskFinalized(String taskId) {
- *         Task task = tasks.get(taskId);
- *         return task != null && task.status().state().isFinal();
- *     }
- * }
- * }
- * - *

CDI Extension Pattern

- *
{@code
- * @ApplicationScoped
- * @Alternative
- * @Priority(50)  // Higher than default InMemoryTaskStore
- * public class JpaDatabaseTaskStore implements TaskStore, TaskStateProvider {
- *     @PersistenceContext
- *     EntityManager em;
- *
- *     @Transactional
- *     public void save(Task task) {
- *         TaskEntity entity = toEntity(task);
- *         em.merge(entity);
- *     }
- * }
- * }
- * - *

Thread Safety

- * Implementations must be thread-safe. Multiple threads will call methods concurrently - * for different tasks. Concurrent {@code save()} calls for the same task must handle - * conflicts appropriately (last-write-wins, optimistic locking, etc.). - * - *

List Operation Performance

- * The {@link #list(io.a2a.spec.ListTasksParams)} method may need to scan and filter - * many tasks. Database implementations should: - *
    - *
  • Use indexes on contextId, status, lastUpdatedAt
  • - *
  • Implement efficient pagination with stable ordering
  • - *
  • Consider caching for frequently-accessed task lists
  • - *
- * - * @see TaskManager - * @see TaskStateProvider - * @see InMemoryTaskStore - * @see io.a2a.server.requesthandlers.DefaultRequestHandler - */ -public interface TaskStore { - /** - * Saves or updates a task. - * - * @param task the task to save - * @param isReplicated true if this task update came from a replicated event, - * false if it originated locally. Used to prevent feedback loops - * in replicated scenarios (e.g., don't fire TaskFinalizedEvent for replicated updates) - */ - void save(Task task, boolean isReplicated); - - /** - * Retrieves a task by its ID. - * - * @param taskId the task identifier - * @return the task if found, null otherwise - */ - @Nullable Task get(String taskId); - - /** - * Deletes a task by its ID. - * - * @param taskId the task identifier - */ - void delete(String taskId); - - /** - * List tasks with optional filtering and pagination. - * - * @param params the filtering and pagination parameters - * @return the list of tasks matching the criteria with pagination info - */ - ListTasksResult list(ListTasksParams params); -} diff --git a/server-common/src/main/java/io/a2a/server/tasks/package-info.java b/server-common/src/main/java/io/a2a/server/tasks/package-info.java deleted file mode 100644 index 1075aded6..000000000 --- a/server-common/src/main/java/io/a2a/server/tasks/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.tasks; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java b/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java deleted file mode 100644 index 4cb1f82b5..000000000 --- a/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java +++ /dev/null @@ -1,108 +0,0 @@ -package io.a2a.server.util; - -import java.util.List; -import java.util.UUID; - -import io.a2a.spec.Artifact; -import io.a2a.spec.DataPart; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import org.jspecify.annotations.Nullable; - -/** - * Utility functions for creating A2A Artifact objects. - */ -public final class ArtifactUtils { - - private ArtifactUtils() { - // Utility class - prevent instantiation - } - - /** - * Creates a new Artifact object. - * - * @param name The human-readable name of the artifact. - * @param parts The list of {@code Part} objects forming the artifact's content. - * @param description An optional description of the artifact. - * @return A new {@code Artifact} object with a generated artifact_id. - */ - public static Artifact newArtifact(String name, List> parts, @Nullable String description) { - return new Artifact( - UUID.randomUUID().toString(), - name, - description, - parts, - null, - null - ); - } - - /** - * Creates a new Artifact object with empty description. - * - * @param name The human-readable name of the artifact. - * @param parts The list of {@code Part} objects forming the artifact's content. - * @return A new {@code Artifact} object with a generated artifact_id. - */ - public static Artifact newArtifact(String name, List> parts) { - return newArtifact(name, parts, null); - } - - /** - * Creates a new Artifact object containing only a single TextPart. - * - * @param name The human-readable name of the artifact. - * @param text The text content of the artifact. - * @param description An optional description of the artifact. - * @return A new {@code Artifact} object with a generated artifact_id. - */ - public static Artifact newTextArtifact(String name, String text, @Nullable String description) { - return newArtifact( - name, - List.of(new TextPart(text)), - description - ); - } - - /** - * Creates a new Artifact object containing only a single TextPart with empty description. - * - * @param name The human-readable name of the artifact. - * @param text The text content of the artifact. - * @return A new {@code Artifact} object with a generated artifact_id. - */ - public static Artifact newTextArtifact(String name, String text) { - return newTextArtifact(name, text, null); - } - - /** - * Creates a new Artifact object containing only a single DataPart. - *

- * Supports any JSON value type: objects (Map), arrays (List), primitives (String, Number, Boolean), or null. - * - * @param name The human-readable name of the artifact. - * @param data The structured data content of the artifact (JSON object, array, primitive, or null). - * @param description An optional description of the artifact. - * @return A new {@code Artifact} object with a generated artifact_id. - */ - public static Artifact newDataArtifact(String name, Object data, @Nullable String description) { - return newArtifact( - name, - List.of(new DataPart(data)), - description - ); - } - - /** - * Creates a new Artifact object containing only a single DataPart with empty description. - *

- * Supports any JSON value type: objects (Map), arrays (List), primitives (String, Number, Boolean), or null. - * - * @param name The human-readable name of the artifact. - * @param data The structured data content of the artifact (JSON object, array, primitive, or null). - * @return A new {@code Artifact} object with a generated artifact_id. - */ - public static Artifact newDataArtifact(String name, Object data) { - return newDataArtifact(name, data, null); - } -} diff --git a/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java b/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java deleted file mode 100644 index eee254ba3..000000000 --- a/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java +++ /dev/null @@ -1,164 +0,0 @@ -package io.a2a.server.util.async; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; - -import io.a2a.server.config.A2AConfigProvider; -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@ApplicationScoped -public class AsyncExecutorProducer { - - private static final Logger LOGGER = LoggerFactory.getLogger(AsyncExecutorProducer.class); - private static final String A2A_EXECUTOR_CORE_POOL_SIZE = "a2a.executor.core-pool-size"; - private static final String A2A_EXECUTOR_MAX_POOL_SIZE = "a2a.executor.max-pool-size"; - private static final String A2A_EXECUTOR_KEEP_ALIVE_SECONDS = "a2a.executor.keep-alive-seconds"; - private static final String A2A_EXECUTOR_QUEUE_CAPACITY = "a2a.executor.queue-capacity"; - - @Inject - A2AConfigProvider configProvider; - - /** - * Core pool size for async agent execution thread pool. - *

- * Property: {@code a2a.executor.core-pool-size}
- * Default: 5
- * Note: Property override requires a configurable {@link A2AConfigProvider} on the classpath. - */ - int corePoolSize; - - /** - * Maximum pool size for async agent execution thread pool. - *

- * Property: {@code a2a.executor.max-pool-size}
- * Default: 50
- * Note: Property override requires a configurable {@link A2AConfigProvider} on the classpath. - */ - int maxPoolSize; - - /** - * Keep-alive time for idle threads (seconds). - *

- * Property: {@code a2a.executor.keep-alive-seconds}
- * Default: 60
- * Note: Property override requires a configurable {@link A2AConfigProvider} on the classpath. - */ - long keepAliveSeconds; - - /** - * Queue capacity for pending tasks. - *

- * Property: {@code a2a.executor.queue-capacity}
- * Default: 100
- * Note: Must be bounded to allow pool growth to maxPoolSize. - * When queue is full, new threads are created up to maxPoolSize. - */ - int queueCapacity; - - private @Nullable ExecutorService executor; - - @PostConstruct - public void init() { - corePoolSize = Integer.parseInt(configProvider.getValue(A2A_EXECUTOR_CORE_POOL_SIZE)); - maxPoolSize = Integer.parseInt(configProvider.getValue(A2A_EXECUTOR_MAX_POOL_SIZE)); - keepAliveSeconds = Long.parseLong(configProvider.getValue(A2A_EXECUTOR_KEEP_ALIVE_SECONDS)); - queueCapacity = Integer.parseInt(configProvider.getValue(A2A_EXECUTOR_QUEUE_CAPACITY)); - - LOGGER.info("Initializing async executor: corePoolSize={}, maxPoolSize={}, keepAliveSeconds={}, queueCapacity={}", - corePoolSize, maxPoolSize, keepAliveSeconds, queueCapacity); - - // CRITICAL: Use ArrayBlockingQueue (bounded) instead of LinkedBlockingQueue (unbounded). - // With unbounded queue, ThreadPoolExecutor NEVER grows beyond corePoolSize because the - // queue never fills. This causes executor pool exhaustion during concurrent requests when - // EventConsumer polling threads hold all core threads and agent tasks queue indefinitely. - // Bounded queue enables pool growth: when queue is full, new threads are created up to - // maxPoolSize, preventing agent execution starvation. - ThreadPoolExecutor tpe = new ThreadPoolExecutor( - corePoolSize, - maxPoolSize, - keepAliveSeconds, - TimeUnit.SECONDS, - new ArrayBlockingQueue<>(queueCapacity), - new A2AThreadFactory() - ); - - // CRITICAL: Allow core threads to timeout after keepAliveSeconds when idle. - // By default, ThreadPoolExecutor only times out threads above corePoolSize. - // Without this, core threads accumulate during testing and never clean up. - // This is essential for streaming scenarios where many short-lived tasks create threads - // for agent execution and cleanup callbacks, but those threads remain idle afterward. - tpe.allowCoreThreadTimeOut(true); - - executor = tpe; - } - - @PreDestroy - public void close() { - if (executor == null) { - return; - } - LOGGER.info("Shutting down async executor"); - executor.shutdown(); - try { - if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { - LOGGER.warn("Executor did not terminate in 10 seconds, forcing shutdown"); - executor.shutdownNow(); - } - } catch (InterruptedException e) { - LOGGER.error("Interrupted while waiting for executor shutdown", e); - executor.shutdownNow(); - Thread.currentThread().interrupt(); - } - } - - @Produces - @Internal - public Executor produce() { - if (executor == null) { - throw new IllegalStateException("Executor not initialized - @PostConstruct not called"); - } - return executor; - } - - /** - * Log current executor pool statistics for diagnostics. - * Useful for debugging pool exhaustion or sizing issues. - */ - public void logPoolStats() { - if (executor instanceof ThreadPoolExecutor tpe) { - LOGGER.info("Executor pool stats: active={}/{}, queued={}/{}, completed={}, total={}", - tpe.getActiveCount(), - tpe.getPoolSize(), - tpe.getQueue().size(), - queueCapacity, - tpe.getCompletedTaskCount(), - tpe.getTaskCount()); - } - } - - private static class A2AThreadFactory implements ThreadFactory { - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix = "a2a-agent-executor-"; - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement()); - t.setDaemon(false); - return t; - } - } - -} diff --git a/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java b/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java deleted file mode 100644 index 4d1d4f9c4..000000000 --- a/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java +++ /dev/null @@ -1,257 +0,0 @@ -package io.a2a.server.util.async; - -import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; - -import io.a2a.util.Assert; -import mutiny.zero.BackpressureStrategy; -import mutiny.zero.Tube; -import mutiny.zero.TubeConfiguration; -import mutiny.zero.ZeroPublisher; -import mutiny.zero.operators.Transform; -import org.jspecify.annotations.Nullable; - -public class AsyncUtils { - - private static final int DEFAULT_TUBE_BUFFER_SIZE = 256; - - public static TubeConfiguration createTubeConfig() { - return createTubeConfig(DEFAULT_TUBE_BUFFER_SIZE); - } - - public static TubeConfiguration createTubeConfig(int bufferSize) { - return new TubeConfiguration() - .withBackpressureStrategy(BackpressureStrategy.BUFFER) - .withBufferSize(256); - } - - public static void consumer( - TubeConfiguration config, - Flow.Publisher source, - Function nextFunction, - Consumer errorConsumer) { - - BiFunction, T, Boolean> nextBiFunction = new BiFunction, T, Boolean>() { - @Override - public Boolean apply(Consumer throwableConsumer, T t) { - return nextFunction.apply(t); - } - }; - - ZeroPublisher.create(config, tube -> { - source.subscribe(new ConsumingSubscriber<>(nextBiFunction, errorConsumer)); - }) - .subscribe(new Flow.Subscriber() { - private Flow.@Nullable Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(Object item) { - if (subscription != null) { - subscription.request(1); - } - } - - @Override - public void onError(Throwable throwable) { - if (subscription != null) { - subscription.cancel(); - } - } - - @Override - public void onComplete() { - if (subscription != null) { - subscription.cancel(); - } - } - }); - } - - public static Flow.Publisher processor( - TubeConfiguration config, - Flow.Publisher source, - BiFunction, T, Boolean> nextFunction) { - - return ZeroPublisher.create(config, tube -> { - source.subscribe(new ProcessingSubscriber<>(tube, nextFunction)); - }); - } - - public static Flow.Publisher convertingProcessor(Flow.Publisher source, Function converterFunction) { - return new Transform<>(source, converterFunction); - } - - - private static abstract class AbstractSubscriber implements Flow.Subscriber { - private Flow.@Nullable Subscription subscription; - private final BiFunction, T, Boolean> nextFunction; - private final @Nullable Consumer publishNextConsumer; - private final @Nullable Consumer failureOrCompleteConsumer; - - protected AbstractSubscriber( - BiFunction, T, Boolean> nextFunction, - @Nullable Consumer publishNextConsumer, - @Nullable Consumer failureOrCompleteConsumer) { - Assert.checkNotNullParam("nextFunction", nextFunction); - this.nextFunction = nextFunction; - this.publishNextConsumer = publishNextConsumer; - this.failureOrCompleteConsumer = failureOrCompleteConsumer; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(T item) { - AtomicReference errorRaised = new AtomicReference<>(); - - Consumer errorConsumer = t -> { - errorRaised.set(t); - onError(t); - }; - boolean continueProcessing = false; - if (errorRaised.get() == null) { - try { - continueProcessing = nextFunction.apply(errorConsumer, item); - } catch (Throwable t) { - errorConsumer.accept(t); - } - } - if (!continueProcessing || errorRaised.get() != null) { - if (subscription != null) { - subscription.cancel(); - } - } else { - if (publishNextConsumer != null) { - publishNextConsumer.accept(item); - } - if (subscription != null) { - subscription.request(1); - } - } - } - - - @Override - public void onError(Throwable throwable) { - if (subscription != null) { - subscription.cancel(); - } - if (failureOrCompleteConsumer != null) { - failureOrCompleteConsumer.accept(throwable); - } - } - - @Override - public void onComplete() { - if (subscription != null) { - subscription.cancel(); - } - if (failureOrCompleteConsumer != null) { - failureOrCompleteConsumer.accept(null); - } - } - } - - private static class ConsumingSubscriber extends AbstractSubscriber { - public ConsumingSubscriber(BiFunction, T, Boolean> nextFunction, - @Nullable Consumer failureOrCompleteConsumer) { - super(nextFunction, null, failureOrCompleteConsumer); - } - } - - private static class ProcessingSubscriber extends AbstractSubscriber { - public ProcessingSubscriber(Tube tube, BiFunction, T, Boolean> nextFunction) { - super( - nextFunction, - tube::send, - t -> { - if (t == null) { - tube.complete(); - } else { - tube.fail(t); - } - } - ); - Assert.checkNotNullParam("tube", tube); - } - } - - private static class ConvertingProcessingSubscriber implements Flow.Subscriber { - private Flow.@Nullable Subscription subscription; - private final Tube tube; - private final BiFunction, T, N> converterBiFunction; - - public ConvertingProcessingSubscriber(Tube tube, Function converterFunction) { - Assert.checkNotNullParam("tube", tube); - Assert.checkNotNullParam("converterFunction", converterFunction); - this.tube = tube; - this.converterBiFunction = (throwableConsumer, t) -> converterFunction.apply(t); - } - - public ConvertingProcessingSubscriber(Tube tube, BiFunction, T, N> converterBiFunction) { - Assert.checkNotNullParam("tube", tube); - Assert.checkNotNullParam("converterBiFunction", converterBiFunction); - this.tube = tube; - this.converterBiFunction = converterBiFunction; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(T item) { - AtomicBoolean errorRaised = new AtomicBoolean(false); - Consumer errorConsumer = t -> { - errorRaised.set(true); - onError(t); - }; - - N converted = null; - try { - converted = converterBiFunction.apply(errorConsumer, item); - } catch (Throwable t) { - errorConsumer.accept(t); - return; - } - if (!errorRaised.get()) { - tube.send(converted); - if (subscription != null) { - subscription.request(1); - } - } - } - - @Override - public void onError(Throwable throwable) { - if (subscription != null) { - subscription.cancel(); - } - tube.fail(throwable); - } - - @Override - public void onComplete() { - if (subscription != null) { - subscription.cancel(); - } - tube.complete(); - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java b/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java deleted file mode 100644 index 24ff7f5d1..000000000 --- a/server-common/src/main/java/io/a2a/server/util/async/EventConsumerExecutorProducer.java +++ /dev/null @@ -1,93 +0,0 @@ -package io.a2a.server.util.async; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Qualifier; - -import org.jspecify.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static java.lang.annotation.ElementType.*; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Produces a dedicated executor for EventConsumer polling threads. - *

- * CRITICAL: EventConsumer polling must use a separate executor from AgentExecutor because: - *

    - *
  • EventConsumer threads are I/O-bound (blocking on queue.poll()), not CPU-bound
  • - *
  • One EventConsumer thread needed per active queue (can be 100+ concurrent)
  • - *
  • Threads are mostly idle, waiting for events
  • - *
  • Using the same bounded pool as AgentExecutor causes deadlock when pool exhausted
  • - *
- *

- * Uses a cached thread pool (unbounded) with automatic thread reclamation: - *

    - *
  • Creates threads on demand as EventConsumers start
  • - *
  • Idle threads automatically terminated after 10 seconds
  • - *
  • No queue saturation since threads are created as needed
  • - *
- */ -@ApplicationScoped -public class EventConsumerExecutorProducer { - private static final Logger LOGGER = LoggerFactory.getLogger(EventConsumerExecutorProducer.class); - - /** - * Qualifier annotation for EventConsumer executor injection. - */ - @Retention(RUNTIME) - @Target({METHOD, FIELD, PARAMETER, TYPE}) - @Qualifier - public @interface EventConsumerExecutor { - } - - /** - * Thread factory for EventConsumer threads. - */ - private static class EventConsumerThreadFactory implements ThreadFactory { - private final AtomicInteger threadNumber = new AtomicInteger(1); - - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r, "a2a-event-consumer-" + threadNumber.getAndIncrement()); - thread.setDaemon(true); - return thread; - } - } - - private @Nullable ExecutorService executor; - - @Produces - @EventConsumerExecutor - @ApplicationScoped - public Executor eventConsumerExecutor() { - // Cached thread pool with 10s idle timeout (reduced from default 60s): - // - Creates threads on demand as EventConsumers start - // - Reclaims idle threads after 10s to prevent accumulation during fast test execution - // - Perfect for I/O-bound EventConsumer polling which blocks on queue.poll() - // - 10s timeout balances thread reuse (production) vs cleanup (testing) - executor = new ThreadPoolExecutor( - 0, // corePoolSize - no core threads - Integer.MAX_VALUE, // maxPoolSize - unbounded - 10, TimeUnit.SECONDS, // keepAliveTime - 10s idle timeout - new SynchronousQueue<>(), // queue - same as cached pool - new EventConsumerThreadFactory() - ); - - LOGGER.info("Initialized EventConsumer executor: cached thread pool (unbounded, 10s idle timeout)"); - - return executor; - } -} diff --git a/server-common/src/main/java/io/a2a/server/util/async/Internal.java b/server-common/src/main/java/io/a2a/server/util/async/Internal.java deleted file mode 100644 index 7774d4838..000000000 --- a/server-common/src/main/java/io/a2a/server/util/async/Internal.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.server.util.async; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import jakarta.inject.Qualifier; - -/** - * CDI qualifier for internal async executor beans. - *

- * This qualifier is used to distinguish internal async executors from - * application-level executors when multiple executor beans exist. - *

- */ -@Qualifier -@Retention(RetentionPolicy.RUNTIME) -public @interface Internal { -} diff --git a/server-common/src/main/java/io/a2a/server/util/async/package-info.java b/server-common/src/main/java/io/a2a/server/util/async/package-info.java deleted file mode 100644 index daf4dcf5b..000000000 --- a/server-common/src/main/java/io/a2a/server/util/async/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.util.async; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/util/package-info.java b/server-common/src/main/java/io/a2a/server/util/package-info.java deleted file mode 100644 index 897a999fb..000000000 --- a/server-common/src/main/java/io/a2a/server/util/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -@NullMarked -package io.a2a.server.util; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java b/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java deleted file mode 100644 index ba02222e6..000000000 --- a/server-common/src/main/java/io/a2a/server/util/sse/SseFormatter.java +++ /dev/null @@ -1,136 +0,0 @@ -package io.a2a.server.util.sse; - -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; -import io.a2a.jsonrpc.common.wrappers.A2AResponse; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; - -/** - * Framework-agnostic utility for formatting A2A responses as Server-Sent Events (SSE). - *

- * Provides static methods to serialize A2A responses to JSON and format them as SSE events. - * This allows HTTP server frameworks (Vert.x, Jakarta/WildFly, etc.) to use their own - * reactive libraries for publisher mapping while sharing the serialization logic. - *

- * Example usage (Quarkus/Vert.x with Mutiny): - *

{@code
- * Flow.Publisher> responses = handler.onMessageSendStream(request, context);
- * AtomicLong eventId = new AtomicLong(0);
- *
- * Multi sseEvents = Multi.createFrom().publisher(responses)
- *     .map(response -> SseFormatter.formatResponseAsSSE(response, eventId.getAndIncrement()));
- *
- * sseEvents.subscribe().with(sseEvent -> httpResponse.write(Buffer.buffer(sseEvent)));
- * }
- *

- * Example usage (Jakarta/WildFly with custom reactive library): - *

{@code
- * Flow.Publisher jsonStrings = restHandler.getJsonPublisher();
- * AtomicLong eventId = new AtomicLong(0);
- *
- * Flow.Publisher sseEvents = mapPublisher(jsonStrings,
- *     json -> SseFormatter.formatJsonAsSSE(json, eventId.getAndIncrement()));
- * }
- */ -public class SseFormatter { - - private SseFormatter() { - // Utility class - prevent instantiation - } - - /** - * Format an A2A response as an SSE event. - *

- * Serializes the response to JSON and formats as: - *

-     * data: {"jsonrpc":"2.0","result":{...},"id":123}
-     * id: 0
-     *
-     * 
- * - * @param response the A2A response to format - * @param eventId the SSE event ID - * @return SSE-formatted string (ready to write to HTTP response) - */ - public static String formatResponseAsSSE(A2AResponse response, long eventId) { - String jsonData = serializeResponse(response); - return "data: " + jsonData + "\nid: " + eventId + "\n\n"; - } - - /** - * Format a pre-serialized JSON string as an SSE event. - *

- * Wraps the JSON in SSE format as: - *

-     * data: {"jsonrpc":"2.0","result":{...},"id":123}
-     * id: 0
-     *
-     * 
- *

- * Use this when you already have JSON strings (e.g., from REST transport) - * and just need to add SSE formatting. - * - * @param jsonString the JSON string to wrap - * @param eventId the SSE event ID - * @return SSE-formatted string (ready to write to HTTP response) - */ - public static String formatJsonAsSSE(String jsonString, long eventId) { - return "data: " + jsonString + "\nid: " + eventId + "\n\n"; - } - - /** - * Serialize an A2AResponse to JSON string. - */ - private static String serializeResponse(A2AResponse response) { - // For error responses, use standard JSON-RPC error format - if (response instanceof A2AErrorResponse error) { - return JSONRPCUtils.toJsonRPCErrorResponse(error.getId(), error.getError()); - } - if (response.getError() != null) { - return JSONRPCUtils.toJsonRPCErrorResponse(response.getId(), response.getError()); - } - - // Convert domain response to protobuf message and serialize - com.google.protobuf.MessageOrBuilder protoMessage = convertToProto(response); - return JSONRPCUtils.toJsonRPCResultResponse(response.getId(), protoMessage); - } - - /** - * Convert A2AResponse to protobuf message for serialization. - */ - private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse response) { - if (response instanceof GetTaskResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); - } else if (response instanceof CancelTaskResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); - } else if (response instanceof SendMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessage(r.getResult()); - } else if (response instanceof ListTasksResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTasksResult(r.getResult()); - } else if (response instanceof CreateTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.createTaskPushNotificationConfigResponse(r.getResult()); - } else if (response instanceof GetTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getTaskPushNotificationConfigResponse(r.getResult()); - } else if (response instanceof ListTaskPushNotificationConfigResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.listTaskPushNotificationConfigResponse(r.getResult()); - } else if (response instanceof DeleteTaskPushNotificationConfigResponse) { - // DeleteTaskPushNotificationConfig has no result body, just return empty message - return com.google.protobuf.Empty.getDefaultInstance(); - } else if (response instanceof GetExtendedAgentCardResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.getExtendedCardResponse(r.getResult()); - } else if (response instanceof SendStreamingMessageResponse r) { - return io.a2a.grpc.utils.ProtoUtils.ToProto.taskOrMessageStream(r.getResult()); - } else { - throw new IllegalArgumentException("Unknown response type: " + response.getClass().getName()); - } - } -} diff --git a/server-common/src/main/java/io/a2a/server/util/sse/package-info.java b/server-common/src/main/java/io/a2a/server/util/sse/package-info.java deleted file mode 100644 index 7e668b632..000000000 --- a/server-common/src/main/java/io/a2a/server/util/sse/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Server-Sent Events (SSE) formatting utilities for A2A streaming responses. - *

- * Provides framework-agnostic conversion of {@code Flow.Publisher>} to - * {@code Flow.Publisher} with SSE formatting, enabling easy integration with - * any HTTP server framework (Vert.x, Jakarta Servlet, etc.). - */ -@NullMarked -package io.a2a.server.util.sse; - -import org.jspecify.annotations.NullMarked; diff --git a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java b/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java deleted file mode 100644 index da667e538..000000000 --- a/server-common/src/main/java/io/a2a/server/version/A2AVersionValidator.java +++ /dev/null @@ -1,122 +0,0 @@ -package io.a2a.server.version; - -import java.util.List; -import java.util.stream.Collectors; - -import io.a2a.server.ServerCallContext; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.VersionNotSupportedError; - -/** - * Utility class for validating A2A protocol version compatibility between clients and agents. - * - *

Version validation follows semantic versioning rules: - *

    - *
  • Major versions must match exactly (1.x can only talk to 1.x)
  • - *
  • Minor versions are compatible (1.0 client can talk to 1.1 server and vice versa)
  • - *
- * - *

If the client does not specify a version, the current protocol version - * ({@link AgentInterface#CURRENT_PROTOCOL_VERSION}) is assumed as the default. - */ -public class A2AVersionValidator { - - /** - * Validates that the client's requested protocol version is compatible with the agent's - * supported versions across all interfaces. - * - * @param agentCard the agent card containing the supported interfaces with their protocol versions - * @param context the server call context containing the requested protocol version - * @throws VersionNotSupportedError if the versions are incompatible - */ - public static void validateProtocolVersion(AgentCard agentCard, ServerCallContext context) - throws VersionNotSupportedError { - String requestedVersion = context.getRequestedProtocolVersion(); - - // If client didn't specify a version, default to current version - if (requestedVersion == null || requestedVersion.trim().isEmpty()) { - requestedVersion = AgentInterface.CURRENT_PROTOCOL_VERSION; - } - - // Collect all unique protocol versions from all supported interfaces - List supportedVersions = agentCard.supportedInterfaces().stream() - .map(AgentInterface::protocolVersion) - .distinct() - .collect(Collectors.toList()); - - if (!isVersionCompatible(supportedVersions, requestedVersion)) { - throw new VersionNotSupportedError( - null, - "Protocol version '" + requestedVersion + "' is not supported. " + - "Supported versions: " + supportedVersions, - null); - } - } - - /** - * Checks if the requested version is compatible with the supported version. - * - *

Compatibility rules: - *

    - *
  • Major versions must match exactly
  • - *
  • Minor versions are compatible (any x.Y works with x.Z)
  • - *
- * - * @param supportedVersions the version supported by the agent (e.g., ["1.0", "1.1"]) - * @param requestedVersion the version requested by the client (e.g., "1.1") - * @return true if versions are compatible, false otherwise - */ - static boolean isVersionCompatible(List supportedVersions, String requestedVersion) { - if (supportedVersions == null) { - return false; - } - for (String supportedVersion : supportedVersions) { - try { - VersionParts supportedParts = parseVersion(supportedVersion); - VersionParts requestedParts = parseVersion(requestedVersion); - - // Major versions must match exactly - if (supportedParts.major == requestedParts.major) { - return true; - } - // Minor versions are compatible - any 1.x can talk to any 1.y - } catch (IllegalArgumentException e) { - // If we can't parse the version, consider it incompatible - return false; - } - } - return false; - } - - /** - * Parses a version string into major and minor components. - * - * @param version the version string (e.g., "1.0") - * @return the parsed version parts - * @throws IllegalArgumentException if the version format is invalid - */ - private static VersionParts parseVersion(String version) { - if (version == null || version.trim().isEmpty()) { - throw new IllegalArgumentException("Version cannot be null or empty"); - } - - String[] parts = version.split("\\."); - if (parts.length < 2) { - throw new IllegalArgumentException("Version must have at least major.minor format: " + version); - } - - try { - int major = Integer.parseInt(parts[0]); - int minor = Integer.parseInt(parts[1]); - return new VersionParts(major, minor); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Invalid version format: " + version, e); - } - } - - /** - * Simple record to hold version components. - */ - private record VersionParts(int major, int minor) {} -} diff --git a/server-common/src/main/resources/META-INF/a2a-defaults.properties b/server-common/src/main/resources/META-INF/a2a-defaults.properties deleted file mode 100644 index 719be9e7a..000000000 --- a/server-common/src/main/resources/META-INF/a2a-defaults.properties +++ /dev/null @@ -1,25 +0,0 @@ -# A2A SDK Default Configuration Values -# These values are used when no other configuration source provides them - -# DefaultRequestHandler - Blocking call timeouts -# Timeout for agent execution to complete (seconds) -# Increase for slow agents: LLM-based, data processing, external APIs -a2a.blocking.agent.timeout.seconds=30 - -# Timeout for event consumption/persistence to complete (seconds) -# Ensures TaskStore is fully updated before returning to client -a2a.blocking.consumption.timeout.seconds=5 - -# AsyncExecutorProducer - Thread pool configuration -# Core pool size for async agent execution -a2a.executor.core-pool-size=5 - -# Maximum pool size for async agent execution -a2a.executor.max-pool-size=50 - -# Keep-alive time for idle threads (seconds) -a2a.executor.keep-alive-seconds=60 - -# Queue capacity for pending tasks (must be bounded to enable pool growth) -# When queue is full, new threads are created up to max-pool-size -a2a.executor.queue-capacity=100 diff --git a/server-common/src/main/resources/META-INF/beans.xml b/server-common/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 9b2940fc2..000000000 --- a/server-common/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java b/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java deleted file mode 100644 index 1c913ab7f..000000000 --- a/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java +++ /dev/null @@ -1,253 +0,0 @@ -package io.a2a.server; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.logging.Handler; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; -import org.junit.jupiter.api.Test; - -public class AgentCardValidatorTest { - - private AgentCard.Builder createTestAgentCardBuilder() { - return AgentCard.builder() - .name("Test Agent") - .description("Test Description") - .supportedInterfaces(Collections.singletonList( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder().build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.emptyList()); - } - - @Test - void testValidationWithSimpleAgentCard() { - // Create a simple AgentCard (uses default JSONRPC transport) - AgentCard agentCard = createTestAgentCardBuilder() - .build(); - - // Define available transports - Set availableTransports = Set.of(TransportProtocol.JSONRPC.asString()); - - // Validation should now pass - assertDoesNotThrow(() -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - } - - @Test - void testValidationWithMultipleTransports() { - // Create AgentCard that specifies multiple transports - AgentCard agentCard = createTestAgentCardBuilder() - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"), - new AgentInterface(TransportProtocol.GRPC.asString(), "http://localhost:9000") - )) - .build(); - - // Define available transports - Set availableTransports = - Set.of(TransportProtocol.JSONRPC.asString(), TransportProtocol.GRPC.asString()); - - // Validation should now pass - assertDoesNotThrow(() -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - } - - @Test - void testLogWarningWhenExtraTransportsFound() { - // Create an AgentCard with only JSONRPC - AgentCard agentCard = createTestAgentCardBuilder() - .supportedInterfaces(Collections.singletonList(new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) - .build(); - - // Define available transports (more than in AgentCard) - Set availableTransports = - Set.of(TransportProtocol.JSONRPC.asString(), TransportProtocol.GRPC.asString()); - - // Capture logs - Logger logger = Logger.getLogger(AgentCardValidator.class.getName()); - TestLogHandler testLogHandler = new TestLogHandler(); - logger.addHandler(testLogHandler); - - try { - AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports); - } finally { - logger.removeHandler(testLogHandler); - } - - // Assert that a warning was logged - assertTrue(testLogHandler.getLogMessages().stream() - .anyMatch(msg -> msg.contains("AgentCard does not include all available transports. Missing: [GRPC]"))); - } - - @Test - void testValidationWithUnavailableTransport() { - // Create a simple AgentCard (uses default JSONRPC transport) - AgentCard agentCard = createTestAgentCardBuilder() - .build(); - - // Define available transports (empty) - Set availableTransports = Collections.emptySet(); - - // Should throw exception because no transports are available - IllegalStateException exception = assertThrows(IllegalStateException.class, - () -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - assertTrue(exception.getMessage().contains("unavailable transports: [JSONRPC]")); - } - - @Test - void testGlobalSkipProperty() { - System.setProperty(AgentCardValidator.SKIP_PROPERTY, "true"); - try { - AgentCard agentCard = createTestAgentCardBuilder() - .build(); - - Set availableTransports = Collections.emptySet(); - - assertDoesNotThrow(() -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - } finally { - System.clearProperty(AgentCardValidator.SKIP_PROPERTY); - } - } - - @Test - void testSkipJsonrpcProperty() { - System.setProperty(AgentCardValidator.SKIP_JSONRPC_PROPERTY, "true"); - try { - AgentCard agentCard = createTestAgentCardBuilder() - .supportedInterfaces(Collections.singletonList(new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) - .build(); - - Set availableTransports = Set.of(TransportProtocol.GRPC.asString()); - - assertDoesNotThrow(() -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - } finally { - System.clearProperty(AgentCardValidator.SKIP_JSONRPC_PROPERTY); - } - } - - @Test - void testSkipGrpcProperty() { - System.setProperty(AgentCardValidator.SKIP_GRPC_PROPERTY, "true"); - try { - AgentCard agentCard = createTestAgentCardBuilder() - .supportedInterfaces(Collections.singletonList(new AgentInterface(TransportProtocol.GRPC.asString(), "http://localhost:9000"))) - .build(); - - Set availableTransports = Set.of(TransportProtocol.JSONRPC.asString()); - - assertDoesNotThrow(() -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - } finally { - System.clearProperty(AgentCardValidator.SKIP_GRPC_PROPERTY); - } - } - - @Test - void testSkipRestProperty() { - System.setProperty(AgentCardValidator.SKIP_REST_PROPERTY, "true"); - try { - AgentCard agentCard = createTestAgentCardBuilder() - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.HTTP_JSON.asString(), "http://localhost:8080") - )) - .build(); - - Set availableTransports = Set.of(TransportProtocol.JSONRPC.asString()); - - assertDoesNotThrow(() -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - } finally { - System.clearProperty(AgentCardValidator.SKIP_REST_PROPERTY); - } - } - - @Test - void testMultipleTransportsWithMixedSkipProperties() { - System.setProperty(AgentCardValidator.SKIP_GRPC_PROPERTY, "true"); - try { - AgentCard agentCard = createTestAgentCardBuilder() - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"), - new AgentInterface(TransportProtocol.GRPC.asString(), "http://localhost:9000"), - new AgentInterface(TransportProtocol.HTTP_JSON.asString(), "http://localhost:8080") - )) - .build(); - - Set availableTransports = Set.of(TransportProtocol.JSONRPC.asString()); - - IllegalStateException exception = assertThrows(IllegalStateException.class, - () -> AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports)); - assertTrue(exception.getMessage().contains("unavailable transports: [HTTP+JSON]")); - } finally { - System.clearProperty(AgentCardValidator.SKIP_GRPC_PROPERTY); - } - } - - @Test - void testSkipPropertiesFilterWarnings() { - System.setProperty(AgentCardValidator.SKIP_GRPC_PROPERTY, "true"); - try { - AgentCard agentCard = createTestAgentCardBuilder() - .supportedInterfaces(Collections.singletonList(new AgentInterface(TransportProtocol.JSONRPC.asString(), "http://localhost:9999"))) - .build(); - - Set availableTransports = Set.of( - TransportProtocol.JSONRPC.asString(), - TransportProtocol.GRPC.asString(), - TransportProtocol.HTTP_JSON.asString() - ); - - Logger logger = Logger.getLogger(AgentCardValidator.class.getName()); - TestLogHandler testLogHandler = new TestLogHandler(); - logger.addHandler(testLogHandler); - - try { - AgentCardValidator.validateTransportConfiguration(agentCard, availableTransports); - } finally { - logger.removeHandler(testLogHandler); - } - - boolean foundWarning = testLogHandler.getLogMessages().stream() - .anyMatch(msg -> msg.contains("Missing: [HTTP+JSON]")); - assertTrue(foundWarning); - - boolean grpcMentioned = testLogHandler.getLogMessages().stream() - .anyMatch(msg -> msg.contains("GRPC")); - assertFalse(grpcMentioned); - } finally { - System.clearProperty(AgentCardValidator.SKIP_GRPC_PROPERTY); - } - } - - // A simple log handler for testing - private static class TestLogHandler extends Handler { - private final List logMessages = new java.util.ArrayList<>(); - - @Override - public void publish(LogRecord record) { - logMessages.add(record.getMessage()); - } - - @Override - public void flush() { - } - - @Override - public void close() throws SecurityException { - } - - public List getLogMessages() { - return logMessages; - } - } -} diff --git a/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java b/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java deleted file mode 100644 index 911b81540..000000000 --- a/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java +++ /dev/null @@ -1,132 +0,0 @@ -package io.a2a.server; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import io.a2a.server.auth.User; -import org.junit.jupiter.api.Test; - -class ServerCallContextTest { - - @Test - void testDefaultConstructor() { - User user = new TestUser(); - Map state = new HashMap<>(); - - ServerCallContext context = new ServerCallContext(user, state, new HashSet<>()); - - assertEquals(user, context.getUser()); - assertEquals(state, context.getState()); - assertTrue(context.getRequestedExtensions().isEmpty()); - assertTrue(context.getActivatedExtensions().isEmpty()); - } - - @Test - void testConstructorWithRequestedExtensions() { - User user = new TestUser(); - Map state = new HashMap<>(); - Set requestedExtensions = Set.of("foo", "bar"); - - ServerCallContext context = new ServerCallContext(user, state, requestedExtensions); - - assertEquals(user, context.getUser()); - assertEquals(state, context.getState()); - assertEquals(requestedExtensions, context.getRequestedExtensions()); - assertTrue(context.getActivatedExtensions().isEmpty()); - } - - @Test - void testConstructorWithRequestedAndActivatedExtensions() { - User user = new TestUser(); - Map state = new HashMap<>(); - Set requestedExtensions = Set.of("foo", "bar"); - ServerCallContext context = new ServerCallContext(user, state, requestedExtensions); - - // Manually activate extensions since they start empty - context.activateExtension("foo"); - - assertEquals(user, context.getUser()); - assertEquals(state, context.getState()); - assertEquals(requestedExtensions, context.getRequestedExtensions()); - assertEquals(Set.of("foo"), context.getActivatedExtensions()); - } - - @Test - void testExtensionActivation() { - User user = new TestUser(); - Map state = new HashMap<>(); - Set requestedExtensions = Set.of("foo", "bar"); - - ServerCallContext context = new ServerCallContext(user, state, requestedExtensions); - - // Initially no extensions are activated - assertFalse(context.isExtensionActivated("foo")); - assertFalse(context.isExtensionActivated("bar")); - - // Activate an extension - context.activateExtension("foo"); - assertTrue(context.isExtensionActivated("foo")); - assertFalse(context.isExtensionActivated("bar")); - - // Activate another extension - context.activateExtension("bar"); - assertTrue(context.isExtensionActivated("foo")); - assertTrue(context.isExtensionActivated("bar")); - - // Deactivate an extension - context.deactivateExtension("foo"); - assertFalse(context.isExtensionActivated("foo")); - assertTrue(context.isExtensionActivated("bar")); - } - - @Test - void testExtensionRequested() { - User user = new TestUser(); - Map state = new HashMap<>(); - Set requestedExtensions = Set.of("foo", "bar"); - - ServerCallContext context = new ServerCallContext(user, state, requestedExtensions); - - assertTrue(context.isExtensionRequested("foo")); - assertTrue(context.isExtensionRequested("bar")); - assertFalse(context.isExtensionRequested("baz")); - } - - @Test - void testExtensionCollectionsAreDefensiveCopies() { - User user = new TestUser(); - Map state = new HashMap<>(); - Set requestedExtensions = Set.of("foo", "bar"); - - ServerCallContext context = new ServerCallContext(user, state, requestedExtensions); - - // Modifying returned sets should not affect the context - Set returnedRequested = context.getRequestedExtensions(); - returnedRequested.add("baz"); - assertFalse(context.isExtensionRequested("baz")); - - context.activateExtension("foo"); - Set returnedActivated = context.getActivatedExtensions(); - returnedActivated.add("bar"); - assertFalse(context.isExtensionActivated("bar")); - } - - // Simple test implementation of User interface - private static class TestUser implements User { - @Override - public boolean isAuthenticated() { - return true; - } - - @Override - public String getUsername() { - return "test-user"; - } - } -} diff --git a/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java b/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java deleted file mode 100644 index 2fc0c62e9..000000000 --- a/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java +++ /dev/null @@ -1,432 +0,0 @@ -package io.a2a.server.agentexecution; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockStatic; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; - -public class RequestContextTest { - - private static MessageSendConfiguration defaultConfiguration() { - return MessageSendConfiguration.builder() - .acceptedOutputModes(List.of()) - .blocking(false) - .build(); - } - - @Test - public void testInitWithoutParams() { - RequestContext context = new RequestContext.Builder().build(); - - assertNull(context.getMessage()); - assertNotNull(context.getTaskId()); // Generated UUID - assertNotNull(context.getContextId()); // Generated UUID - assertNull(context.getTask()); - assertTrue(context.getRelatedTasks().isEmpty()); - } - - @Test - public void testInitWithParamsNoIds() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - UUID taskId = UUID.fromString("00000000-0000-0000-0000-000000000001"); - UUID contextId = UUID.fromString("00000000-0000-0000-0000-000000000002"); - - try (MockedStatic mockedUUID = mockStatic(UUID.class)) { - mockedUUID.when(UUID::randomUUID) - .thenReturn(taskId) - .thenReturn(contextId); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .build(); - - // getMessage() returns a new Message with generated IDs, not the original - assertNotNull(context.getMessage()); - assertEquals(taskId.toString(), context.getTaskId()); - assertEquals(taskId.toString(), context.getMessage().taskId()); - assertEquals(contextId.toString(), context.getContextId()); - assertEquals(contextId.toString(), context.getMessage().contextId()); - } - } - - @Test - public void testInitWithTaskId() { - String taskId = "task-123"; - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId(taskId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(taskId) - .build(); - - assertEquals(taskId, context.getTaskId()); - assertEquals(taskId, mockParams.message().taskId()); - } - - @Test - public void testInitWithContextId() { - String contextId = "context-456"; - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).contextId(contextId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setContextId(contextId) - .build(); - - assertEquals(contextId, context.getContextId()); - assertEquals(contextId, mockParams.message().contextId()); - } - - @Test - public void testInitWithBothIds() { - String taskId = "task-123"; - String contextId = "context-456"; - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId(taskId).contextId(contextId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(taskId) - .setContextId(contextId) - .build(); - - assertEquals(taskId, context.getTaskId()); - assertEquals(taskId, mockParams.message().taskId()); - assertEquals(contextId, context.getContextId()); - assertEquals(contextId, mockParams.message().contextId()); - } - - @Test - public void testInitWithTask() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTask(mockTask) - .build(); - - assertEquals(mockTask, context.getTask()); - } - - @Test - public void testGetUserInputNoParams() { - RequestContext context = new RequestContext.Builder().build(); - assertEquals("", context.getUserInput(null)); - } - - @Test - public void testAttachRelatedTask() { - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); - - RequestContext context = new RequestContext.Builder().build(); - assertEquals(0, context.getRelatedTasks().size()); - - context.attachRelatedTask(mockTask); - assertEquals(1, context.getRelatedTasks().size()); - assertEquals(mockTask, context.getRelatedTasks().get(0)); - - Task anotherTask = mock(Task.class); - context.attachRelatedTask(anotherTask); - assertEquals(2, context.getRelatedTasks().size()); - assertEquals(anotherTask, context.getRelatedTasks().get(1)); - } - - @Test - public void testCheckOrGenerateTaskIdWithExistingTaskId() { - String existingId = "existing-task-id"; - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId(existingId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .build(); - - assertEquals(existingId, context.getTaskId()); - assertEquals(existingId, mockParams.message().taskId()); - } - - @Test - public void testCheckOrGenerateContextIdWithExistingContextId() { - String existingId = "existing-context-id"; - - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).contextId(existingId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .build(); - - assertEquals(existingId, context.getContextId()); - assertEquals(existingId, mockParams.message().contextId()); - } - - @Test - public void testInitRaisesErrorOnTaskIdMismatch() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); - - InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> - new RequestContext.Builder() - .setParams(mockParams) - .setTaskId("wrong-task-id") - .setTask(mockTask) - .build()); - - assertTrue(error.getMessage().contains("bad task id")); - } - - @Test - public void testInitRaisesErrorOnContextIdMismatch() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); - - InvalidParamsError error = assertThrows(InvalidParamsError.class, () -> - new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(mockTask.id()) - .setContextId("wrong-context-id") - .setTask(mockTask) - .build()); - - assertTrue(error.getMessage().contains("bad context id")); - } - - @Test - public void testWithRelatedTasksProvided() { - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); - - List relatedTasks = new ArrayList<>(); - relatedTasks.add(mockTask); - relatedTasks.add(mock(Task.class)); - - RequestContext context = new RequestContext.Builder() - .setRelatedTasks(relatedTasks) - .build(); - - assertEquals(relatedTasks, context.getRelatedTasks()); - assertEquals(2, context.getRelatedTasks().size()); - } - - @Test - public void testMessagePropertyWithoutParams() { - RequestContext context = new RequestContext.Builder().build(); - assertNull(context.getMessage()); - } - - @Test - public void testMessagePropertyWithParams() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .build(); - - // getMessage() returns a new Message with generated IDs, not the original - assertNotNull(context.getMessage()); - assertEquals(mockMessage.role(), context.getMessage().role()); - assertEquals(mockMessage.parts(), context.getMessage().parts()); - } - - @Test - public void testInitWithExistingIdsInMessage() { - String existingTaskId = "existing-task-id"; - String existingContextId = "existing-context-id"; - - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))) - .taskId(existingTaskId).contextId(existingContextId).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .build(); - - assertEquals(existingTaskId, context.getTaskId()); - assertEquals(existingContextId, context.getContextId()); - } - - @Test - public void testInitWithTaskIdAndExistingTaskIdMatch() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(mockTask.id()) - .setTask(mockTask) - .build(); - - assertEquals(mockTask.id(), context.getTaskId()); - assertEquals(mockTask, context.getTask()); - } - - @Test - public void testInitWithContextIdAndExistingContextIdMatch() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).taskId("task-123").contextId("context-456").build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - var mockTask = Task.builder().id("task-123").contextId("context-456").status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(mockTask.id()) - .setContextId(mockTask.contextId()) - .setTask(mockTask) - .build(); - - assertEquals(mockTask.contextId(), context.getContextId()); - assertEquals(mockTask, context.getTask()); - } - - @Test - void testMessageBuilderGeneratesId() { - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .build(); - - assertNotNull(mockMessage.messageId()); - assertFalse(mockMessage.messageId().isEmpty()); - } - - @Test - void testMessageBuilderUsesProvidedId() { - var mockMessage = Message.builder().messageId("123").role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .build(); - - assertEquals("123", mockMessage.messageId()); - } - - @Test - public void testBuilderGeneratesIdsWhenNoParams() { - RequestContext context = new RequestContext.Builder() - .build(); - - assertNotNull(context.getTaskId()); - assertNotNull(context.getContextId()); - assertFalse(context.getTaskId().isEmpty()); - assertFalse(context.getContextId().isEmpty()); - } - - @Test - public void testBuilderPreservesProvidedIdsWhenNoParams() { - String providedTaskId = "my-task-id"; - String providedContextId = "my-context-id"; - - RequestContext context = new RequestContext.Builder() - .setTaskId(providedTaskId) - .setContextId(providedContextId) - .build(); - - assertEquals(providedTaskId, context.getTaskId()); - assertEquals(providedContextId, context.getContextId()); - } - - @Test - public void testBuilderUpdatesMessageWithBuilderIds() { - // Regression test for Gemini review: ensure message gets updated when builder provides IDs - String builderTaskId = "builder-task-id"; - String builderContextId = "builder-context-id"; - - // Message has no IDs, but builder provides them - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(builderTaskId) - .setContextId(builderContextId) - .build(); - - // Both context and message should have the builder IDs - assertEquals(builderTaskId, context.getTaskId()); - assertEquals(builderContextId, context.getContextId()); - assertEquals(builderTaskId, context.getMessage().taskId()); // KEY: message must be updated - assertEquals(builderContextId, context.getMessage().contextId()); // KEY: message must be updated - } - - @Test - public void testMessageIdsTakePrecedenceWhenBothPresent() { - // When both builder and message provide IDs, they must match (or throw) - String sharedTaskId = "shared-task-id"; - String sharedContextId = "shared-context-id"; - - var mockMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(List.of(new TextPart(""))) - .taskId(sharedTaskId) - .contextId(sharedContextId) - .build(); - var mockParams = MessageSendParams.builder().message(mockMessage).configuration(defaultConfiguration()).build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(sharedTaskId) // Same as message - .setContextId(sharedContextId) // Same as message - .build(); - - assertEquals(sharedTaskId, context.getTaskId()); - assertEquals(sharedContextId, context.getContextId()); - assertEquals(sharedTaskId, context.getMessage().taskId()); - assertEquals(sharedContextId, context.getMessage().contextId()); - } - - @Test - public void testBuilderPreservesTenantWhenUpdatingMessage() { - // Regression test for Gemini review: ensure tenant is preserved when message is updated - String tenantId = "customer-123"; - String builderTaskId = "builder-task-id"; - - var mockMessage = Message.builder().role(Message.Role.ROLE_USER).parts(List.of(new TextPart(""))).build(); - var mockParams = MessageSendParams.builder() - .message(mockMessage) - .configuration(defaultConfiguration()) - .tenant(tenantId) - .build(); - - RequestContext context = new RequestContext.Builder() - .setParams(mockParams) - .setTaskId(builderTaskId) // Forces message update - .build(); - - // Verify the message was updated with builder's task ID - assertNotNull(context.getMessage()); - assertEquals(builderTaskId, context.getMessage().taskId()); - - // KEY: Verify tenant wasn't lost during message update - assertEquals(tenantId, context.getTenant()); - } -} diff --git a/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java b/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java deleted file mode 100644 index 2b1913355..000000000 --- a/server-common/src/test/java/io/a2a/server/events/EnhancedRunnableTest.java +++ /dev/null @@ -1,136 +0,0 @@ -package io.a2a.server.events; - -import org.junit.jupiter.api.Test; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * Tests for EnhancedRunnable to verify callback registration enforcement. - * These tests ensure that callbacks cannot be added after execution starts, - * preventing race conditions in agent execution. - */ -public class EnhancedRunnableTest { - - @Test - public void testCannotAddCallbackAfterStart() { - EnhancedRunnable runnable = new EnhancedRunnable() { - @Override - public void run() { - // Empty - } - }; - - // Add callback before start - should succeed - AtomicBoolean called = new AtomicBoolean(false); - runnable.addDoneCallback((r) -> called.set(true)); - - // Mark as started - runnable.markStarted(); - - // Try to add callback after start - should fail - IllegalStateException exception = assertThrows(IllegalStateException.class, - () -> runnable.addDoneCallback((r) -> {})); - - assertTrue(exception.getMessage().contains("Cannot add callback after runnable has started")); - } - - @Test - public void testCallbacksInvokedAfterCompletion() throws Exception { - EnhancedRunnable runnable = new EnhancedRunnable() { - @Override - public void run() { - // Empty - } - }; - - AtomicBoolean callback1Called = new AtomicBoolean(false); - AtomicBoolean callback2Called = new AtomicBoolean(false); - - runnable.addDoneCallback((r) -> callback1Called.set(true)); - runnable.addDoneCallback((r) -> callback2Called.set(true)); - runnable.markStarted(); - - CompletableFuture.runAsync(runnable, Executors.newSingleThreadExecutor()) - .thenRun(runnable::invokeDoneCallbacks) - .get(); - - assertTrue(callback1Called.get()); - assertTrue(callback2Called.get()); - } - - @Test - public void testMultipleCallbacksBeforeStart() { - EnhancedRunnable runnable = new EnhancedRunnable() { - @Override - public void run() { - // Empty - } - }; - - // Should be able to add multiple callbacks before start - assertDoesNotThrow(() -> { - runnable.addDoneCallback((r) -> {}); - runnable.addDoneCallback((r) -> {}); - runnable.addDoneCallback((r) -> {}); - }); - - // Mark as started - runnable.markStarted(); - - // Now adding should fail - assertThrows(IllegalStateException.class, - () -> runnable.addDoneCallback((r) -> {})); - } - - @Test - public void testErrorHandling() { - EnhancedRunnable runnable = new EnhancedRunnable() { - @Override - public void run() { - throw new RuntimeException("Test error"); - } - }; - - AtomicBoolean callbackInvoked = new AtomicBoolean(false); - runnable.addDoneCallback((r) -> { - callbackInvoked.set(true); - assertNotNull(r.getError()); - assertEquals("Test error", r.getError().getMessage()); - }); - - runnable.markStarted(); - - try { - runnable.run(); - } catch (RuntimeException e) { - runnable.setError(e); - } - - runnable.invokeDoneCallbacks(); - assertTrue(callbackInvoked.get()); - } - - @Test - public void testMarkStartedIdempotent() { - EnhancedRunnable runnable = new EnhancedRunnable() { - @Override - public void run() { - // Empty - } - }; - - // Should be able to call markStarted multiple times - assertDoesNotThrow(() -> { - runnable.markStarted(); - runnable.markStarted(); - runnable.markStarted(); - }); - - // But callbacks should still be blocked - assertThrows(IllegalStateException.class, - () -> runnable.addDoneCallback((r) -> {})); - } -} diff --git a/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java b/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java deleted file mode 100644 index e31fa9b4b..000000000 --- a/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java +++ /dev/null @@ -1,570 +0,0 @@ -package io.a2a.server.events; - -import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Flow; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.A2AError; -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class EventConsumerTest { - - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; - private static final String TASK_ID = "123"; // Must match MINIMAL_TASK id - - private EventQueue eventQueue; - private EventConsumer eventConsumer; - private MainEventBus mainEventBus; - private MainEventBusProcessor mainEventBusProcessor; - - private static final String MINIMAL_TASK = """ - { - "id": "123", - "contextId": "session-xyz", - "status": {"state": "TASK_STATE_SUBMITTED"} - } - """; - - private static final String MESSAGE_PAYLOAD = """ - { - "role": "ROLE_AGENT", - "parts": [{"text": "test message"}], - "messageId": "111" - } - """; - - @BeforeEach - public void init() { - // Set up MainEventBus and processor for production-like test environment - InMemoryTaskStore taskStore = new InMemoryTaskStore(); - mainEventBus = new MainEventBus(); - InMemoryQueueManager queueManager = new InMemoryQueueManager(taskStore, mainEventBus); - mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); - EventQueueUtil.start(mainEventBusProcessor); - - eventQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .taskId(TASK_ID) - .mainEventBus(mainEventBus) - .build().tap(); - eventConsumer = new EventConsumer(eventQueue); - } - - @AfterEach - public void cleanup() { - if (mainEventBusProcessor != null) { - mainEventBusProcessor.setCallback(null); // Clear any test callbacks - EventQueueUtil.stop(mainEventBusProcessor); - } - } - - /** - * Helper to wait for MainEventBusProcessor to process an event. - * Replaces polling patterns with deterministic callback-based waiting. - * - * @param action the action that triggers event processing - * @throws InterruptedException if waiting is interrupted - * @throws AssertionError if processing doesn't complete within timeout - */ - private void waitForEventProcessing(Runnable action) throws InterruptedException { - CountDownLatch processingLatch = new CountDownLatch(1); - mainEventBusProcessor.setCallback(new MainEventBusProcessorCallback() { - @Override - public void onEventProcessed(String taskId, Event event) { - processingLatch.countDown(); - } - - @Override - public void onTaskFinalized(String taskId) { - // Not needed for basic event processing wait - } - }); - - try { - action.run(); - assertTrue(processingLatch.await(5, TimeUnit.SECONDS), - "MainEventBusProcessor should have processed the event within timeout"); - } finally { - mainEventBusProcessor.setCallback(null); - } - } - - @Test - public void testConsumeOneTaskEvent() throws Exception { - Task event = fromJson(MINIMAL_TASK, Task.class); - enqueueAndConsumeOneEvent(event); - } - - @Test - public void testConsumeOneMessageEvent() throws Exception { - Event event = fromJson(MESSAGE_PAYLOAD, Message.class); - enqueueAndConsumeOneEvent(event); - } - - @Test - public void testConsumeOneA2AErrorEvent() throws Exception { - Event event = new A2AError(-1, "", null); - enqueueAndConsumeOneEvent(event); - } - - @Test - public void testConsumeOneJsonRpcErrorEvent() throws Exception { - Event event = new A2AError(123, "Some Error", null); - enqueueAndConsumeOneEvent(event); - } - - @Test - public void testConsumeOneQueueEmpty() throws A2AServerException { - assertThrows(A2AServerException.class, () -> eventConsumer.consumeOne()); - } - - @Test - public void testConsumeAllMultipleEvents() throws JsonProcessingException { - List events = List.of( - fromJson(MINIMAL_TASK, Task.class), - TaskArtifactUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); - - for (Event event : events) { - eventQueue.enqueueEvent(event); - } - - Flow.Publisher publisher = eventConsumer.consumeAll(); - final List receivedEvents = new ArrayList<>(); - final AtomicReference error = new AtomicReference<>(); - - publisher.subscribe(getSubscriber(receivedEvents, error)); - - assertNull(error.get()); - assertEquals(events.size(), receivedEvents.size()); - for (int i = 0; i < events.size(); i++) { - assertSame(events.get(i), receivedEvents.get(i)); - } - } - - @Test - public void testConsumeUntilMessage() throws Exception { - List events = List.of( - fromJson(MINIMAL_TASK, Task.class), - TaskArtifactUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); - - for (Event event : events) { - eventQueue.enqueueEvent(event); - } - - Flow.Publisher publisher = eventConsumer.consumeAll(); - final List receivedEvents = new ArrayList<>(); - final AtomicReference error = new AtomicReference<>(); - - publisher.subscribe(getSubscriber(receivedEvents, error)); - - assertNull(error.get()); - assertEquals(3, receivedEvents.size()); - for (int i = 0; i < 3; i++) { - assertSame(events.get(i), receivedEvents.get(i)); - } - } - - @Test - public void testConsumeMessageEvents() throws Exception { - Message message = fromJson(MESSAGE_PAYLOAD, Message.class); - Message message2 = Message.builder(message).build(); - - List events = List.of(message, message2); - - for (Event event : events) { - eventQueue.enqueueEvent(event); - } - - Flow.Publisher publisher = eventConsumer.consumeAll(); - final List receivedEvents = new ArrayList<>(); - final AtomicReference error = new AtomicReference<>(); - - publisher.subscribe(getSubscriber(receivedEvents, error)); - - assertNull(error.get()); - // The stream is closed after the first Message - assertEquals(1, receivedEvents.size()); - assertSame(message, receivedEvents.get(0)); - } - - @Test - public void testConsumeTaskInputRequired() { - Task task = Task.builder() - .id(TASK_ID) - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_INPUT_REQUIRED)) - .build(); - List events = List.of( - task, - TaskArtifactUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); - for (Event event : events) { - eventQueue.enqueueEvent(event); - } - - Flow.Publisher publisher = eventConsumer.consumeAll(); - final List receivedEvents = new ArrayList<>(); - final AtomicReference error = new AtomicReference<>(); - - publisher.subscribe(getSubscriber(receivedEvents, error)); - - assertNull(error.get()); - // The stream is closed after the input_required task - assertEquals(1, receivedEvents.size()); - assertSame(task, receivedEvents.get(0)); - } - - private Flow.Subscriber getSubscriber(List receivedEvents, AtomicReference error) { - return new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(EventQueueItem item) { - receivedEvents.add(item.getEvent()); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }; - } - - @Test - public void testCreateAgentRunnableDoneCallbackSetsError() { - EnhancedRunnable mockRunnable = new EnhancedRunnable() { - @Override - public void run() { - // Mock implementation - } - }; - - Throwable testError = new RuntimeException("Test error"); - mockRunnable.setError(testError); - - EnhancedRunnable.DoneCallback callback = eventConsumer.createAgentRunnableDoneCallback(); - callback.done(mockRunnable); - - // The error should be stored in the event consumer - assertEquals(testError, getEventConsumerError()); - } - - @Test - public void testCreateAgentRunnableDoneCallbackNoError() { - EnhancedRunnable mockRunnable = new EnhancedRunnable() { - @Override - public void run() { - // Mock implementation - } - }; - - // No error set on runnable - assertNull(mockRunnable.getError()); - - EnhancedRunnable.DoneCallback callback = eventConsumer.createAgentRunnableDoneCallback(); - callback.done(mockRunnable); - - // The error should remain null - assertNull(getEventConsumerError()); - } - - @Test - public void testConsumeAllRaisesStoredException() throws InterruptedException { - // Set an error in the event consumer - setEventConsumerError(new RuntimeException("Stored error")); - - Flow.Publisher publisher = eventConsumer.consumeAll(); - final AtomicReference receivedError = new AtomicReference<>(); - - final CountDownLatch errorLatch = new CountDownLatch(1); - - - publisher.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscription.request(1); - } - - @Override - public void onNext(EventQueueItem item) { - // Should not be called - errorLatch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - receivedError.set(throwable); - errorLatch.countDown(); - } - - @Override - public void onComplete() { - // Should not be called - errorLatch.countDown(); - } - }); - - // Wait for error callback with timeout - assertTrue(errorLatch.await(5, TimeUnit.SECONDS), "Test timed out waiting for onError callback."); - - assertNotNull(receivedError.get()); - assertEquals("Stored error", receivedError.get().getMessage()); - } - - @Test - public void testConsumeAllStopsOnQueueClosed() throws Exception { - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .mainEventBus(mainEventBus) - .build().tap(); - EventConsumer consumer = new EventConsumer(queue); - - // Close the queue immediately - queue.close(); - - Flow.Publisher publisher = consumer.consumeAll(); - final List receivedEvents = new ArrayList<>(); - final AtomicReference completed = new AtomicReference<>(false); - final CountDownLatch completionLatch = new CountDownLatch(1); - - publisher.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(EventQueueItem item) { - receivedEvents.add(item.getEvent()); - } - - @Override - public void onError(Throwable throwable) { - // Should not be called - completionLatch.countDown(); - } - - @Override - public void onComplete() { - completed.set(true); - completionLatch.countDown(); - } - }); - - // Wait for completion with timeout - assertTrue(completionLatch.await(5, TimeUnit.SECONDS), "Test timed out waiting for onComplete callback."); - - // Should complete immediately with no events - assertTrue(completed.get()); - assertEquals(0, receivedEvents.size()); - } - - - @Test - public void testConsumeAllHandlesQueueClosedException() throws Exception { - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .mainEventBus(mainEventBus) - .build().tap(); - EventConsumer consumer = new EventConsumer(queue); - - // Add a message event (which will complete the stream) - Event message = fromJson(MESSAGE_PAYLOAD, Message.class); - - // Use callback to wait for event processing - waitForEventProcessing(() -> queue.enqueueEvent(message)); - - // Close the queue before consuming - queue.close(); - - Flow.Publisher publisher = consumer.consumeAll(); - final List receivedEvents = new ArrayList<>(); - final AtomicReference completed = new AtomicReference<>(false); - final CountDownLatch completionLatch = new CountDownLatch(1); - - publisher.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(EventQueueItem item) { - receivedEvents.add(item.getEvent()); - } - - @Override - public void onError(Throwable throwable) { - // Should not be called - completionLatch.countDown(); - } - - @Override - public void onComplete() { - completed.set(true); - completionLatch.countDown(); - } - }); - - // Wait for completion with timeout - assertTrue(completionLatch.await(5, TimeUnit.SECONDS), "Test timed out waiting for onComplete callback."); - - // Should have received the message and completed - assertTrue(completed.get()); - assertEquals(1, receivedEvents.size()); - assertSame(message, receivedEvents.get(0)); - } - - @Test - public void testConsumeAllTerminatesOnQueueClosedEvent() throws Exception { - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .mainEventBus(mainEventBus) - .build().tap(); - EventConsumer consumer = new EventConsumer(queue); - - // Enqueue a QueueClosedEvent (poison pill) - QueueClosedEvent queueClosedEvent = new QueueClosedEvent(TASK_ID); - queue.enqueueEvent(queueClosedEvent); - - Flow.Publisher publisher = consumer.consumeAll(); - final List receivedEvents = new ArrayList<>(); - final AtomicReference completed = new AtomicReference<>(false); - final AtomicReference error = new AtomicReference<>(); - final CountDownLatch completionLatch = new CountDownLatch(1); - - publisher.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(EventQueueItem item) { - receivedEvents.add(item.getEvent()); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - completionLatch.countDown(); - } - - @Override - public void onComplete() { - completed.set(true); - completionLatch.countDown(); - } - }); - - // Wait for completion with timeout - assertTrue(completionLatch.await(5, TimeUnit.SECONDS), "Test timed out waiting for completion callback."); - - // Should complete gracefully without error - assertTrue(completed.get(), "Stream should complete normally"); - assertNull(error.get(), "Stream should not error"); - - // The poison pill should not be delivered to subscribers - assertEquals(0, receivedEvents.size(), "QueueClosedEvent should be intercepted, not delivered"); - } - - private void enqueueAndConsumeOneEvent(Event event) throws Exception { - // Use callback to wait for event processing - waitForEventProcessing(() -> eventQueue.enqueueEvent(event)); - - // Event is now available, consume it directly - Event result = eventConsumer.consumeOne(); - assertNotNull(result, "Event should be available"); - assertSame(event, result); - } - - // Helper methods to access private error field via reflection - private Throwable getEventConsumerError() { - try { - java.lang.reflect.Field errorField = EventConsumer.class.getDeclaredField("error"); - errorField.setAccessible(true); - return (Throwable) errorField.get(eventConsumer); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("Failed to access error field", e); - } - } - - private void setEventConsumerError(Throwable error) { - try { - java.lang.reflect.Field errorField = EventConsumer.class.getDeclaredField("error"); - errorField.setAccessible(true); - errorField.set(eventConsumer, error); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("Failed to set error field", e); - } - } -} diff --git a/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java b/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java deleted file mode 100644 index e59d66d88..000000000 --- a/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java +++ /dev/null @@ -1,497 +0,0 @@ -package io.a2a.server.events; - -import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.spec.A2AError; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class EventQueueTest { - - private EventQueue eventQueue; - private MainEventBus mainEventBus; - private MainEventBusProcessor mainEventBusProcessor; - - private static final String TASK_ID = "123"; // Must match MINIMAL_TASK id - - private static final String MINIMAL_TASK = """ - { - "id": "123", - "contextId": "session-xyz", - "status": {"state": "TASK_STATE_SUBMITTED"} - } - """; - - private static final String MESSAGE_PAYLOAD = """ - { - "role": "ROLE_AGENT", - "parts": [{"text": "test message"}], - "messageId": "111" - } - """; - - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; - - @BeforeEach - public void init() { - // Set up MainEventBus and processor for production-like test environment - InMemoryTaskStore taskStore = new InMemoryTaskStore(); - mainEventBus = new MainEventBus(); - InMemoryQueueManager queueManager = new InMemoryQueueManager(taskStore, mainEventBus); - mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); - EventQueueUtil.start(mainEventBusProcessor); - - eventQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .taskId(TASK_ID) - .mainEventBus(mainEventBus) - .build().tap(); - } - - @AfterEach - public void cleanup() { - if (mainEventBusProcessor != null) { - mainEventBusProcessor.setCallback(null); // Clear any test callbacks - EventQueueUtil.stop(mainEventBusProcessor); - } - } - - /** - * Helper to create a queue with MainEventBus configured (for tests that need event distribution). - */ - private EventQueue createQueueWithEventBus(String taskId) { - return EventQueueUtil.getEventQueueBuilder(mainEventBus) - .taskId(taskId) - .build(); - } - - /** - * Helper to wait for MainEventBusProcessor to process an event. - * Replaces polling patterns with deterministic callback-based waiting. - * - * @param action the action that triggers event processing - * @throws InterruptedException if waiting is interrupted - * @throws AssertionError if processing doesn't complete within timeout - */ - private void waitForEventProcessing(Runnable action) throws InterruptedException { - CountDownLatch processingLatch = new CountDownLatch(1); - mainEventBusProcessor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { - @Override - public void onEventProcessed(String taskId, io.a2a.spec.Event event) { - processingLatch.countDown(); - } - - @Override - public void onTaskFinalized(String taskId) { - // Not needed for basic event processing wait - } - }); - - try { - action.run(); - assertTrue(processingLatch.await(5, TimeUnit.SECONDS), - "MainEventBusProcessor should have processed the event within timeout"); - } finally { - mainEventBusProcessor.setCallback(null); - } - } - - @Test - public void testConstructorDefaultQueueSize() { - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - assertEquals(EventQueue.DEFAULT_QUEUE_SIZE, queue.getQueueSize()); - } - - @Test - public void testConstructorCustomQueueSize() { - int customSize = 500; - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).queueSize(customSize).build(); - assertEquals(customSize, queue.getQueueSize()); - } - - @Test - public void testConstructorInvalidQueueSize() { - // Test zero queue size - assertThrows(IllegalArgumentException.class, () -> EventQueueUtil.getEventQueueBuilder(mainEventBus).queueSize(0).build()); - - // Test negative queue size - assertThrows(IllegalArgumentException.class, () -> EventQueueUtil.getEventQueueBuilder(mainEventBus).queueSize(-10).build()); - } - - @Test - public void testTapCreatesChildQueue() { - EventQueue parentQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - EventQueue childQueue = parentQueue.tap(); - - assertNotNull(childQueue); - assertNotSame(parentQueue, childQueue); - assertEquals(EventQueue.DEFAULT_QUEUE_SIZE, childQueue.getQueueSize()); - } - - @Test - public void testTapOnChildQueueThrowsException() { - EventQueue parentQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - EventQueue childQueue = parentQueue.tap(); - - assertThrows(IllegalStateException.class, () -> childQueue.tap()); - } - - @Test - public void testEnqueueEventPropagagesToChildren() throws Exception { - EventQueue mainQueue = createQueueWithEventBus(TASK_ID); - EventQueue childQueue1 = mainQueue.tap(); - EventQueue childQueue2 = mainQueue.tap(); - - Event event = fromJson(MINIMAL_TASK, Task.class); - mainQueue.enqueueEvent(event); - - // Event should be available in all child queues - // Note: MainEventBusProcessor runs async, so we use dequeueEventItem with timeout - Event child1Event = childQueue1.dequeueEventItem(5000).getEvent(); - Event child2Event = childQueue2.dequeueEventItem(5000).getEvent(); - - assertSame(event, child1Event); - assertSame(event, child2Event); - } - - @Test - public void testMultipleChildQueuesReceiveEvents() throws Exception { - EventQueue mainQueue = createQueueWithEventBus(TASK_ID); - EventQueue childQueue1 = mainQueue.tap(); - EventQueue childQueue2 = mainQueue.tap(); - EventQueue childQueue3 = mainQueue.tap(); - - Event event1 = fromJson(MINIMAL_TASK, Task.class); - Event event2 = fromJson(MESSAGE_PAYLOAD, Message.class); - - mainQueue.enqueueEvent(event1); - mainQueue.enqueueEvent(event2); - - // All child queues should receive both events - // Note: Use timeout for async processing - assertSame(event1, childQueue1.dequeueEventItem(5000).getEvent()); - assertSame(event2, childQueue1.dequeueEventItem(5000).getEvent()); - - assertSame(event1, childQueue2.dequeueEventItem(5000).getEvent()); - assertSame(event2, childQueue2.dequeueEventItem(5000).getEvent()); - - assertSame(event1, childQueue3.dequeueEventItem(5000).getEvent()); - assertSame(event2, childQueue3.dequeueEventItem(5000).getEvent()); - } - - @Test - public void testChildQueueDequeueIndependently() throws Exception { - EventQueue mainQueue = createQueueWithEventBus(TASK_ID); - EventQueue childQueue1 = mainQueue.tap(); - EventQueue childQueue2 = mainQueue.tap(); - EventQueue childQueue3 = mainQueue.tap(); - - Event event = fromJson(MINIMAL_TASK, Task.class); - mainQueue.enqueueEvent(event); - - // Dequeue from child1 first (use timeout for async processing) - Event child1Event = childQueue1.dequeueEventItem(5000).getEvent(); - assertSame(event, child1Event); - - // child2 should still have the event available - Event child2Event = childQueue2.dequeueEventItem(5000).getEvent(); - assertSame(event, child2Event); - - // child3 should still have the event available - Event child3Event = childQueue3.dequeueEventItem(5000).getEvent(); - assertSame(event, child3Event); - } - - - @Test - public void testCloseImmediatePropagationToChildren() throws Exception { - EventQueue parentQueue = createQueueWithEventBus(TASK_ID); - EventQueue childQueue = parentQueue.tap(); - - // Add events to both parent and child - Event event = fromJson(MINIMAL_TASK, Task.class); - parentQueue.enqueueEvent(event); - - assertFalse(childQueue.isClosed()); - try { - assertNotNull(childQueue.dequeueEventItem(5000)); // Child has the event (use timeout) - } catch (EventQueueClosedException e) { - // This is fine if queue closed before dequeue - } - - // Add event again for immediate close test - parentQueue.enqueueEvent(event); - - // Close with immediate=true - parentQueue.close(true); - - assertTrue(parentQueue.isClosed()); - assertTrue(childQueue.isClosed()); - - // Child queue should be cleared due to immediate close - // Child queue should be cleared and closed, so dequeueing should throw - assertThrows(EventQueueClosedException.class, () -> childQueue.dequeueEventItem(-1)); - } - - @Test - public void testEnqueueEventWhenClosed() throws Exception { - EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .taskId(TASK_ID) - .build(); - EventQueue childQueue = mainQueue.tap(); - Event event = fromJson(MINIMAL_TASK, Task.class); - - childQueue.close(); // Close the child queue first (removes from children list) - assertTrue(childQueue.isClosed()); - - // Create a new child queue BEFORE enqueuing (ensures it's in children list for distribution) - EventQueue newChildQueue = mainQueue.tap(); - - // MainQueue accepts events even when closed (for replication support) - // This ensures late-arriving replicated events can be enqueued to closed queues - // Note: MainEventBusProcessor runs asynchronously, so we use dequeueEventItem with timeout - mainQueue.enqueueEvent(event); - - // New child queue should receive the event (old closed child was removed from children list) - EventQueueItem item = newChildQueue.dequeueEventItem(5000); - assertNotNull(item); - Event dequeuedEvent = item.getEvent(); - assertSame(event, dequeuedEvent); - - // Now new child queue is closed and empty, should throw exception - newChildQueue.close(); - assertThrows(EventQueueClosedException.class, () -> newChildQueue.dequeueEventItem(-1)); - } - - @Test - public void testDequeueEventWhenClosedAndEmpty() throws Exception { - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build().tap(); - queue.close(); - assertTrue(queue.isClosed()); - - // Dequeue from closed empty queue should throw exception - assertThrows(EventQueueClosedException.class, () -> queue.dequeueEventItem(-1)); - } - - @Test - public void testDequeueEventWhenClosedButHasEvents() throws Exception { - EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .taskId(TASK_ID) - .build(); - EventQueue childQueue = mainQueue.tap(); - Event event = fromJson(MINIMAL_TASK, Task.class); - - // Use callback to wait for event processing instead of polling - waitForEventProcessing(() -> mainQueue.enqueueEvent(event)); - - // At this point, event has been processed and distributed to childQueue - childQueue.close(); // Graceful close - events should remain - assertTrue(childQueue.isClosed()); - - // Should still be able to dequeue existing events from closed queue - EventQueueItem item = childQueue.dequeueEventItem(5000); - assertNotNull(item); - Event dequeuedEvent = item.getEvent(); - assertSame(event, dequeuedEvent); - - // Now queue is closed and empty, should throw exception - assertThrows(EventQueueClosedException.class, () -> childQueue.dequeueEventItem(-1)); - } - - @Test - public void testEnqueueAndDequeueEvent() throws Exception { - Event event = fromJson(MESSAGE_PAYLOAD, Message.class); - eventQueue.enqueueEvent(event); - Event dequeuedEvent = eventQueue.dequeueEventItem(200).getEvent(); - assertSame(event, dequeuedEvent); - } - - @Test - public void testDequeueEventNoWait() throws Exception { - Event event = fromJson(MINIMAL_TASK, Task.class); - eventQueue.enqueueEvent(event); - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event dequeuedEvent = item.getEvent(); - assertSame(event, dequeuedEvent); - } - - @Test - public void testDequeueEventEmptyQueueNoWait() throws Exception { - EventQueueItem item = eventQueue.dequeueEventItem(-1); - assertNull(item); - } - - @Test - public void testDequeueEventWait() throws Exception { - Event event = TaskStatusUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - eventQueue.enqueueEvent(event); - Event dequeuedEvent = eventQueue.dequeueEventItem(1000).getEvent(); - assertSame(event, dequeuedEvent); - } - - @Test - public void testTaskDone() throws Exception { - Event event = TaskArtifactUpdateEvent.builder() - .taskId(TASK_ID) - .contextId("session-xyz") - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(); - eventQueue.enqueueEvent(event); - Event dequeuedEvent = eventQueue.dequeueEventItem(1000).getEvent(); - assertSame(event, dequeuedEvent); - eventQueue.taskDone(); - } - - @Test - public void testEnqueueDifferentEventTypes() throws Exception { - List events = List.of( - new TaskNotFoundError(), - new A2AError(111, "rpc error", null)); - - for (Event event : events) { - eventQueue.enqueueEvent(event); - Event dequeuedEvent = eventQueue.dequeueEventItem(100).getEvent(); - assertSame(event, dequeuedEvent); - } - } - - /** - * Test close behavior sets flag and handles graceful close. - * Backported from Python test: test_close_sets_flag_and_handles_internal_queue_old_python - */ - @Test - public void testCloseGracefulSetsFlag() throws Exception { - Event event = fromJson(MINIMAL_TASK, Task.class); - eventQueue.enqueueEvent(event); - - eventQueue.close(false); // Graceful close - assertTrue(eventQueue.isClosed()); - } - - /** - * Test immediate close behavior. - * Backported from Python test behavior - */ - @Test - public void testCloseImmediateClearsQueue() throws Exception { - Event event = fromJson(MINIMAL_TASK, Task.class); - eventQueue.enqueueEvent(event); - - eventQueue.close(true); // Immediate close - assertTrue(eventQueue.isClosed()); - - // After immediate close, queue should be cleared - // Attempting to dequeue should return null or throw exception - try { - EventQueueItem item = eventQueue.dequeueEventItem(-1); - // If we get here, the item should be null (queue was cleared) - assertNull(item); - } catch (EventQueueClosedException e) { - // This is also acceptable - queue is closed - } - } - - /** - * Test that close is idempotent. - * Backported from Python test: test_close_idempotent - */ - @Test - public void testCloseIdempotent() throws Exception { - eventQueue.close(); - assertTrue(eventQueue.isClosed()); - - // Calling close again should not cause issues - eventQueue.close(); - assertTrue(eventQueue.isClosed()); - - // Test with immediate close as well - EventQueue eventQueue2 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - eventQueue2.close(true); - assertTrue(eventQueue2.isClosed()); - - eventQueue2.close(true); - assertTrue(eventQueue2.isClosed()); - } - - /** - * Test that child queues are NOT automatically closed when parent closes gracefully. - * Children must close themselves, which then notifies parent via reference counting. - */ - @Test - public void testCloseChildQueues() throws Exception { - EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - EventQueue childQueue = mainQueue.tap(); - assertTrue(childQueue != null); - - // Graceful close - parent closes but children remain open - mainQueue.close(); - assertTrue(mainQueue.isClosed()); - assertFalse(childQueue.isClosed()); // Child NOT closed on graceful parent close - - // Immediate close - parent force-closes all children - EventQueue mainQueue2 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - EventQueue childQueue2 = mainQueue2.tap(); - mainQueue2.close(true); // immediate=true - assertTrue(mainQueue2.isClosed()); - assertTrue(childQueue2.isClosed()); // Child IS closed on immediate parent close - } - - /** - * Test reference counting: MainQueue stays open while children are active, - * closes automatically when last child closes. - */ - @Test - public void testMainQueueReferenceCountingStaysOpenWithActiveChildren() throws Exception { - EventQueue mainQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - EventQueue child1 = mainQueue.tap(); - EventQueue child2 = mainQueue.tap(); - - // Close child1 - child1.close(); - - // MainQueue should still be open (child2 active) - assertFalse(mainQueue.isClosed()); - assertTrue(child1.isClosed()); - assertFalse(child2.isClosed()); - - // Close child2 - child2.close(); - - // Now MainQueue should auto-close (no children left) - assertTrue(mainQueue.isClosed()); - assertTrue(child2.isClosed()); - } -} diff --git a/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java b/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java deleted file mode 100644 index 6c9ed4a17..000000000 --- a/server-common/src/test/java/io/a2a/server/events/EventQueueUtil.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.a2a.server.events; - -import java.util.concurrent.atomic.AtomicInteger; - -public class EventQueueUtil { - // Counter for generating unique test taskIds - private static final AtomicInteger TASK_ID_COUNTER = new AtomicInteger(0); - - /** - * Get an EventQueue builder pre-configured with the shared test MainEventBus and a unique taskId. - *

- * Note: Returns MainQueue - tests should call .tap() if they need to consume events. - *

- * - * @return builder with TEST_EVENT_BUS and unique taskId already set - */ - public static EventQueue.EventQueueBuilder getEventQueueBuilder(MainEventBus eventBus) { - return EventQueue.builder(eventBus) - .taskId("test-task-" + TASK_ID_COUNTER.incrementAndGet()); - } - - /** - * Start a MainEventBusProcessor instance. - * - * @param processor the processor to start - */ - public static void start(MainEventBusProcessor processor) { - processor.start(); - } - - /** - * Stop a MainEventBusProcessor instance. - * - * @param processor the processor to stop - */ - public static void stop(MainEventBusProcessor processor) { - processor.stop(); - } -} diff --git a/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java b/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java deleted file mode 100644 index 3e09ff2af..000000000 --- a/server-common/src/test/java/io/a2a/server/events/InMemoryQueueManagerTest.java +++ /dev/null @@ -1,242 +0,0 @@ -package io.a2a.server.events; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.IntStream; - -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.MockTaskStateProvider; -import io.a2a.server.tasks.PushNotificationSender; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class InMemoryQueueManagerTest { - - private InMemoryQueueManager queueManager; - private MockTaskStateProvider taskStateProvider; - private InMemoryTaskStore taskStore; - private MainEventBus mainEventBus; - private MainEventBusProcessor mainEventBusProcessor; - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; - - @BeforeEach - public void setUp() { - taskStateProvider = new MockTaskStateProvider(); - taskStore = new InMemoryTaskStore(); - mainEventBus = new MainEventBus(); - queueManager = new InMemoryQueueManager(taskStateProvider, mainEventBus); - mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); - EventQueueUtil.start(mainEventBusProcessor); - } - - @AfterEach - public void tearDown() { - EventQueueUtil.stop(mainEventBusProcessor); - } - - @Test - public void testAddNewQueue() { - String taskId = "test_task_id"; - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - - queueManager.add(taskId, queue); - - EventQueue retrievedQueue = queueManager.get(taskId); - assertSame(queue, retrievedQueue); - } - - @Test - public void testAddExistingQueueThrowsException() { - String taskId = "test_task_id"; - EventQueue queue1 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - EventQueue queue2 = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - - queueManager.add(taskId, queue1); - - assertThrows(TaskQueueExistsException.class, () -> { - queueManager.add(taskId, queue2); - }); - } - - @Test - public void testGetExistingQueue() { - String taskId = "test_task_id"; - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - - queueManager.add(taskId, queue); - EventQueue result = queueManager.get(taskId); - - assertSame(queue, result); - } - - @Test - public void testGetNonexistentQueue() { - EventQueue result = queueManager.get("nonexistent_task_id"); - assertNull(result); - } - - @Test - public void testTapExistingQueue() { - String taskId = "test_task_id"; - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - - queueManager.add(taskId, queue); - EventQueue tappedQueue = queueManager.tap(taskId); - - assertNotNull(tappedQueue); - - // Tapped queue should be different from original - // (it's a child queue in Java implementation) - assertNotSame(queue, tappedQueue, "Tapped queue should be a different instance from the original."); - } - - @Test - public void testTapNonexistentQueue() { - EventQueue result = queueManager.tap("nonexistent_task_id"); - assertNull(result); - } - - @Test - public void testCloseExistingQueue() { - String taskId = "test_task_id"; - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - - queueManager.add(taskId, queue); - queueManager.close(taskId); - - // Queue should be removed from manager - EventQueue result = queueManager.get(taskId); - assertNull(result); - } - - @Test - public void testCloseNonexistentQueueThrowsException() { - assertThrows(NoTaskQueueException.class, () -> { - queueManager.close("nonexistent_task_id"); - }); - } - - @Test - public void testCreateOrTapNewQueue() { - String taskId = "test_task_id"; - - EventQueue result = queueManager.createOrTap(taskId); - - assertNotNull(result); - // createOrTap now returns ChildQueue, not MainQueue - // MainQueue should be stored in manager - EventQueue retrievedQueue = queueManager.get(taskId); - assertNotNull(retrievedQueue); - // Result should be a ChildQueue (cannot be tapped) - assertThrows(IllegalStateException.class, () -> result.tap()); - } - - @Test - public void testCreateOrTapExistingQueue() { - String taskId = "test_task_id"; - EventQueue originalQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - - queueManager.add(taskId, originalQueue); - EventQueue result = queueManager.createOrTap(taskId); - - assertNotNull(result); - // Should be a tapped (child) queue, not the original - // Original should still be in manager - EventQueue retrievedQueue = queueManager.get(taskId); - assertSame(originalQueue, retrievedQueue); - } - - @Test - public void testConcurrentOperations() throws InterruptedException, ExecutionException { - // Create 10 different task IDs - List taskIds = IntStream.range(0, 10) - .mapToObj(i -> "task_" + i) - .toList(); - - // Add tasks concurrently - List> addFutures = taskIds.stream() - .map(taskId -> CompletableFuture.supplyAsync(() -> { - EventQueue queue = EventQueueUtil.getEventQueueBuilder(mainEventBus).build(); - queueManager.add(taskId, queue); - return taskId; - })) - .toList(); - - // Wait for all add operations to complete - List addedTaskIds = new ArrayList<>(); - for (CompletableFuture future : addFutures) { - addedTaskIds.add(future.get()); - } - - // Verify all tasks were added - assertEquals(taskIds.size(), addedTaskIds.size()); - assertTrue(addedTaskIds.containsAll(taskIds)); - - // Get tasks concurrently - List> getFutures = taskIds.stream() - .map(taskId -> CompletableFuture.supplyAsync(() -> queueManager.get(taskId))) - .toList(); - - // Wait for all get operations to complete - List queues = new ArrayList<>(); - for (CompletableFuture future : getFutures) { - queues.add(future.get()); - } - - // Verify all queues are not null - assertEquals(taskIds.size(), queues.size()); - for (EventQueue queue : queues) { - assertNotNull(queue); - } - - // Verify all tasks are in the manager - for (String taskId : taskIds) { - assertNotNull(queueManager.get(taskId)); - } - } - - @Test - public void testCreateOrTapRaceCondition() throws InterruptedException, ExecutionException { - String taskId = "race_condition_task"; - - // Try to create/tap the same task ID concurrently - List> futures = IntStream.range(0, 5) - .mapToObj(i -> CompletableFuture.supplyAsync(() -> queueManager.createOrTap(taskId))) - .toList(); - - // Wait for all operations to complete - List results = new ArrayList<>(); - for (CompletableFuture future : futures) { - results.add(future.get()); - } - - // All results should be non-null - for (EventQueue result : results) { - assertNotNull(result); - } - - // There should be exactly one MainQueue in the manager - EventQueue managerQueue = queueManager.get(taskId); - assertNotNull(managerQueue); - - // ALL results should be ChildQueues (cannot tap a ChildQueue) - for (EventQueue result : results) { - assertThrows(IllegalStateException.class, () -> result.tap()); - } - - // All ChildQueues should be distinct instances - long distinctCount = results.stream().distinct().count(); - assertEquals(results.size(), distinctCount, "All ChildQueues should be distinct instances"); - } -} diff --git a/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java b/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java deleted file mode 100644 index b9dec6364..000000000 --- a/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package io.a2a.server.extensions; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; -import org.junit.jupiter.api.Test; - -class A2AExtensionsTest { - - @Test - void testGetRequestedExtensions() { - // Test empty list - Set result = A2AExtensions.getRequestedExtensions(Collections.emptyList()); - assertTrue(result.isEmpty()); - - // Test single extension - result = A2AExtensions.getRequestedExtensions(Arrays.asList("foo")); - assertEquals(Set.of("foo"), result); - - // Test multiple extensions in separate values - result = A2AExtensions.getRequestedExtensions(Arrays.asList("foo", "bar")); - assertEquals(Set.of("foo", "bar"), result); - - // Test comma-separated extensions with space - result = A2AExtensions.getRequestedExtensions(Arrays.asList("foo, bar")); - assertEquals(Set.of("foo", "bar"), result); - - // Test comma-separated extensions without space - result = A2AExtensions.getRequestedExtensions(Arrays.asList("foo,bar")); - assertEquals(Set.of("foo", "bar"), result); - - // Test mixed format - result = A2AExtensions.getRequestedExtensions(Arrays.asList("foo", "bar,baz")); - assertEquals(Set.of("foo", "bar", "baz"), result); - - // Test with empty values and extra spaces - result = A2AExtensions.getRequestedExtensions(Arrays.asList("foo,, bar", "baz")); - assertEquals(Set.of("foo", "bar", "baz"), result); - - // Test with leading/trailing spaces - result = A2AExtensions.getRequestedExtensions(Arrays.asList(" foo , bar ", "baz")); - assertEquals(Set.of("foo", "bar", "baz"), result); - - // Test null list - result = A2AExtensions.getRequestedExtensions(null); - assertTrue(result.isEmpty()); - - // Test list with null values - List listWithNulls = Arrays.asList("foo", null, "bar"); - result = A2AExtensions.getRequestedExtensions(listWithNulls); - assertEquals(Set.of("foo", "bar"), result); - } - - @Test - void testFindExtensionByUri() { - AgentExtension ext1 = AgentExtension.builder() - .uri("foo") - .description("The Foo extension") - .build(); - AgentExtension ext2 = AgentExtension.builder() - .uri("bar") - .description("The Bar extension") - .build(); - - AgentCard card = AgentCard.builder() - .name("Test Agent") - .description("Test Agent Description") - .version("1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://test.com"))) - .skills(Collections.emptyList()) - .defaultInputModes(Arrays.asList("text/plain")) - .defaultOutputModes(Arrays.asList("text/plain")) - .capabilities(AgentCapabilities.builder() - .extensions(Arrays.asList(ext1, ext2)) - .build()) - .build(); - - assertEquals(ext1, A2AExtensions.findExtensionByUri(card, "foo")); - assertEquals(ext2, A2AExtensions.findExtensionByUri(card, "bar")); - assertNull(A2AExtensions.findExtensionByUri(card, "baz")); - } - - @Test - void testFindExtensionByUriNoExtensions() { - AgentCard card = AgentCard.builder() - .name("Test Agent") - .description("Test Agent Description") - .version("1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://test.com"))) - .skills(Collections.emptyList()) - .defaultInputModes(Arrays.asList("text/plain")) - .defaultOutputModes(Arrays.asList("text/plain")) - .capabilities(AgentCapabilities.builder() - .extensions(null) - .build()) - .build(); - - assertNull(A2AExtensions.findExtensionByUri(card, "foo")); - } - - @Test - void testFindExtensionByUriNoCapabilities() { - // Test with empty capabilities (no extensions list) - AgentCard card = AgentCard.builder() - .name("Test Agent") - .description("Test Agent Description") - .version("1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://test.com"))) - .skills(Collections.emptyList()) - .defaultInputModes(Arrays.asList("text/plain")) - .defaultOutputModes(Arrays.asList("text/plain")) - .capabilities(AgentCapabilities.builder().build()) - .build(); - - assertNull(A2AExtensions.findExtensionByUri(card, "foo")); - } -} diff --git a/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java b/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java deleted file mode 100644 index c553de317..000000000 --- a/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java +++ /dev/null @@ -1,273 +0,0 @@ -package io.a2a.server.requesthandlers; - - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.function.Consumer; - -import jakarta.enterprise.context.Dependent; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.server.tasks.BasePushNotificationSender; -import io.a2a.server.tasks.InMemoryPushNotificationConfigStore; -import io.a2a.server.tasks.InMemoryTaskStore; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.server.tasks.PushNotificationSender; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; -import io.quarkus.arc.profile.IfBuildProfile; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; - -public class AbstractA2ARequestHandlerTest { - - protected static final AgentCard CARD = createAgentCard(true, true); - - protected static final Task MINIMAL_TASK = Task.builder() - .id("task-123") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - protected static final Message MESSAGE = Message.builder() - .messageId("111") - .role(Message.Role.ROLE_AGENT) - .parts(new TextPart("test message")) - .build(); - private static final String PREFERRED_TRANSPORT = "preferred-transport"; - private static final String A2A_REQUESTHANDLER_TEST_PROPERTIES = "/a2a-requesthandler-test.properties"; - - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; - - protected AgentExecutor executor; - protected TaskStore taskStore; - protected RequestHandler requestHandler; - protected AgentExecutorMethod agentExecutorExecute; - protected AgentExecutorMethod agentExecutorCancel; - protected InMemoryQueueManager queueManager; - protected TestHttpClient httpClient; - protected MainEventBus mainEventBus; - protected MainEventBusProcessor mainEventBusProcessor; - - protected final Executor internalExecutor = Executors.newCachedThreadPool(); - - @BeforeEach - public void init() { - executor = new AgentExecutor() { - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - if (agentExecutorExecute != null) { - agentExecutorExecute.invoke(context, agentEmitter); - } - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - if (agentExecutorCancel != null) { - agentExecutorCancel.invoke(context, agentEmitter); - } - } - }; - - InMemoryTaskStore inMemoryTaskStore = new InMemoryTaskStore(); - taskStore = inMemoryTaskStore; - - // Create push notification components BEFORE MainEventBusProcessor - httpClient = new TestHttpClient(); - PushNotificationConfigStore pushConfigStore = new InMemoryPushNotificationConfigStore(); - PushNotificationSender pushSender = new BasePushNotificationSender(pushConfigStore, httpClient); - - // Create MainEventBus and MainEventBusProcessor (production code path) - mainEventBus = new MainEventBus(); - queueManager = new InMemoryQueueManager(inMemoryTaskStore, mainEventBus); - mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, pushSender, queueManager); - EventQueueUtil.start(mainEventBusProcessor); - - requestHandler = DefaultRequestHandler.create( - executor, taskStore, queueManager, pushConfigStore, mainEventBusProcessor, internalExecutor, internalExecutor); - } - - @AfterEach - public void cleanup() { - agentExecutorExecute = null; - agentExecutorCancel = null; - - // Stop MainEventBusProcessor background thread - if (mainEventBusProcessor != null) { - EventQueueUtil.stop(mainEventBusProcessor); - } - } - - protected static AgentCard createAgentCard(boolean streaming, boolean pushNotifications) { - String preferredTransport = loadPreferredTransportFromProperties(); - AgentCard.Builder builder = AgentCard.builder() - .name("test-card") - .description("A test agent card") - .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, "http://example.com"))) - .version("1.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(streaming) - .pushNotifications(pushNotifications) - .build()) - .defaultInputModes(new ArrayList<>()) - .defaultOutputModes(new ArrayList<>()) - .skills(new ArrayList<>()); - return builder.build(); - } - - private static String loadPreferredTransportFromProperties() { - URL url = AbstractA2ARequestHandlerTest.class.getResource(A2A_REQUESTHANDLER_TEST_PROPERTIES); - Assertions.assertNotNull(url); - Properties properties = new Properties(); - try { - try (InputStream in = url.openStream()){ - properties.load(in); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - - String preferredTransport = properties.getProperty(PREFERRED_TRANSPORT); - Assertions.assertNotNull(preferredTransport); - return preferredTransport; - } - - protected interface AgentExecutorMethod { - void invoke(RequestContext context, AgentEmitter agentEmitter) throws A2AError; - } - - /** - * Helper method to wrap events in EventQueueItem for tests. - * Creates a simple wrapper that marks events as non-replicated (local events). - */ - protected static EventQueueItem wrapEvent(Event event) { - return new EventQueueItem() { - @Override - public Event getEvent() { - return event; - } - - @Override - public boolean isReplicated() { - return false; - } - }; - } - - @Dependent - @IfBuildProfile("test") - protected static class TestHttpClient implements A2AHttpClient { - public final List events = Collections.synchronizedList(new ArrayList<>()); - public volatile CountDownLatch latch; - - @Override - public GetBuilder createGet() { - return null; - } - - @Override - public PostBuilder createPost() { - return new TestHttpClient.TestPostBuilder(); - } - - @Override - public DeleteBuilder createDelete() { - return null; - } - - class TestPostBuilder implements A2AHttpClient.PostBuilder { - private volatile String body; - @Override - public PostBuilder body(String body) { - this.body = body; - return this; - } - - @Override - public A2AHttpResponse post() throws IOException, InterruptedException { - try { - // Parse StreamResponse format to extract the streaming event - // The body contains a wrapper with one of: task, message, statusUpdate, artifactUpdate - StreamingEventKind event = JsonUtil.fromJson(body, StreamingEventKind.class); - events.add(event); - return new A2AHttpResponse() { - @Override - public int status() { - return 200; - } - - @Override - public boolean success() { - return true; - } - - @Override - public String body() { - return ""; - } - }; - } catch (JsonProcessingException e) { - throw new IOException("Failed to parse StreamingEventKind JSON", e); - } finally { - if (latch != null) { - latch.countDown(); - } - } - } - - @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { - return null; - } - - @Override - public PostBuilder url(String s) { - return this; - } - - @Override - public PostBuilder addHeader(String name, String value) { - return this; - } - - @Override - public PostBuilder addHeaders(Map headers) { - return this; - } - - } - } -} diff --git a/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java b/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java deleted file mode 100644 index e69de29bb..000000000 diff --git a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java deleted file mode 100644 index eafcc712a..000000000 --- a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterConcurrencyTest.java +++ /dev/null @@ -1,248 +0,0 @@ -package io.a2a.server.tasks; - -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.spec.UnsupportedOperationError; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * Concurrency tests for AgentEmitter to verify thread-safety of terminal state management. - * These tests ensure that the AtomicBoolean-based terminal state flag prevents race conditions - * when multiple threads attempt to set terminal states concurrently. - */ -public class AgentEmitterConcurrencyTest { - - @Test - public void testConcurrentTerminalStateUpdates() throws InterruptedException { - // Setup - RequestContext context = mock(RequestContext.class); - when(context.getTaskId()).thenReturn("test-task-123"); - when(context.getContextId()).thenReturn("test-context-456"); - - EventQueue eventQueue = mock(EventQueue.class); - AgentEmitter emitter = new AgentEmitter(context, eventQueue); - - // Test concurrent completion attempts - int threadCount = 10; - ExecutorService executor = Executors.newFixedThreadPool(threadCount); - CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch doneLatch = new CountDownLatch(threadCount); - AtomicInteger successCount = new AtomicInteger(0); - AtomicInteger failureCount = new AtomicInteger(0); - - for (int i = 0; i < threadCount; i++) { - executor.submit(() -> { - try { - startLatch.await(); // Wait for all threads to be ready - emitter.complete(); - successCount.incrementAndGet(); - } catch (IllegalStateException e) { - failureCount.incrementAndGet(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } finally { - doneLatch.countDown(); - } - }); - } - - startLatch.countDown(); // Start all threads simultaneously - assertTrue(doneLatch.await(5, TimeUnit.SECONDS), "All threads should complete"); - - // Verify: exactly one success, rest failures - assertEquals(1, successCount.get(), "Exactly one thread should succeed"); - assertEquals(threadCount - 1, failureCount.get(), "All other threads should fail"); - - // Verify: only one event was enqueued - verify(eventQueue, times(1)).enqueueEvent(any()); - - executor.shutdown(); - } - - @Test - public void testConcurrentMixedTerminalStates() throws InterruptedException { - // Setup - RequestContext context = mock(RequestContext.class); - when(context.getTaskId()).thenReturn("test-task-123"); - when(context.getContextId()).thenReturn("test-context-456"); - - EventQueue eventQueue = mock(EventQueue.class); - AgentEmitter emitter = new AgentEmitter(context, eventQueue); - - // Test concurrent different terminal state attempts - ExecutorService executor = Executors.newFixedThreadPool(3); - CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch doneLatch = new CountDownLatch(3); - AtomicInteger successCount = new AtomicInteger(0); - - // Thread 1: complete - executor.submit(() -> { - try { - startLatch.await(); - emitter.complete(); - successCount.incrementAndGet(); - } catch (Exception e) { - // Expected for 2 out of 3 threads - } finally { - doneLatch.countDown(); - } - }); - - // Thread 2: fail - executor.submit(() -> { - try { - startLatch.await(); - emitter.fail(); - successCount.incrementAndGet(); - } catch (Exception e) { - // Expected for 2 out of 3 threads - } finally { - doneLatch.countDown(); - } - }); - - // Thread 3: cancel - executor.submit(() -> { - try { - startLatch.await(); - emitter.cancel(); - successCount.incrementAndGet(); - } catch (Exception e) { - // Expected for 2 out of 3 threads - } finally { - doneLatch.countDown(); - } - }); - - startLatch.countDown(); - assertTrue(doneLatch.await(5, TimeUnit.SECONDS)); - - // Verify: exactly one success - assertEquals(1, successCount.get(), "Exactly one terminal state should succeed"); - verify(eventQueue, times(1)).enqueueEvent(any()); - - executor.shutdown(); - } - - @Test - public void testConcurrentFailWithErrorAndComplete() throws InterruptedException { - // Setup - RequestContext context = mock(RequestContext.class); - when(context.getTaskId()).thenReturn("test-task-123"); - when(context.getContextId()).thenReturn("test-context-456"); - - EventQueue eventQueue = mock(EventQueue.class); - AgentEmitter emitter = new AgentEmitter(context, eventQueue); - - ExecutorService executor = Executors.newFixedThreadPool(2); - CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch doneLatch = new CountDownLatch(2); - AtomicInteger successCount = new AtomicInteger(0); - - executor.submit(() -> { - try { - startLatch.await(); - emitter.fail(new UnsupportedOperationError()); - successCount.incrementAndGet(); - } catch (Exception e) { - // Expected for one thread - } finally { - doneLatch.countDown(); - } - }); - - executor.submit(() -> { - try { - startLatch.await(); - emitter.complete(); - successCount.incrementAndGet(); - } catch (Exception e) { - // Expected for one thread - } finally { - doneLatch.countDown(); - } - }); - - startLatch.countDown(); - assertTrue(doneLatch.await(5, TimeUnit.SECONDS)); - assertEquals(1, successCount.get(), "Exactly one terminal operation should succeed"); - - executor.shutdown(); - } - - @Test - public void testFailWithErrorSetsTerminalState() { - // Setup - RequestContext context = mock(RequestContext.class); - when(context.getTaskId()).thenReturn("test-task-123"); - when(context.getContextId()).thenReturn("test-context-456"); - - EventQueue eventQueue = mock(EventQueue.class); - AgentEmitter emitter = new AgentEmitter(context, eventQueue); - - // Call fail with error - emitter.fail(new UnsupportedOperationError()); - - // Verify terminal state is set - subsequent calls should throw - IllegalStateException exception = assertThrows(IllegalStateException.class, - () -> emitter.complete()); - assertEquals("Cannot update task status - terminal state already reached", - exception.getMessage()); - } - - @Test - public void testFailWithErrorThenFailWithMessage() { - // Setup - RequestContext context = mock(RequestContext.class); - when(context.getTaskId()).thenReturn("test-task-123"); - when(context.getContextId()).thenReturn("test-context-456"); - - EventQueue eventQueue = mock(EventQueue.class); - AgentEmitter emitter = new AgentEmitter(context, eventQueue); - - // Call fail with error - emitter.fail(new UnsupportedOperationError()); - - // Second fail should throw - IllegalStateException exception = assertThrows(IllegalStateException.class, - () -> emitter.fail()); - assertEquals("Cannot update task status - terminal state already reached", - exception.getMessage()); - } - - @Test - public void testNonTerminalThenTerminalState() throws InterruptedException { - // Setup - RequestContext context = mock(RequestContext.class); - when(context.getTaskId()).thenReturn("test-task-123"); - when(context.getContextId()).thenReturn("test-context-456"); - - EventQueue eventQueue = mock(EventQueue.class); - AgentEmitter emitter = new AgentEmitter(context, eventQueue); - - // Non-terminal states should work - emitter.submit(); - emitter.startWork(); - - // Terminal state should work - emitter.complete(); - - // Verify events were enqueued - verify(eventQueue, times(3)).enqueueEvent(any()); - - // Further updates should fail - IllegalStateException exception = assertThrows(IllegalStateException.class, - () -> emitter.startWork()); - assertEquals("Cannot update task status - terminal state already reached", - exception.getMessage()); - } -} diff --git a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java b/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java deleted file mode 100644 index 7c85b9004..000000000 --- a/server-common/src/test/java/io/a2a/server/tasks/AgentEmitterTest.java +++ /dev/null @@ -1,457 +0,0 @@ -package io.a2a.server.tasks; - -import static io.a2a.spec.Message.Role.ROLE_AGENT; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import java.util.Map; - -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueItem; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.spec.Event; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class AgentEmitterTest { - public static final String TEST_TASK_ID = "test-task-id"; - public static final String TEST_TASK_CONTEXT_ID = "test-task-context-id"; - - private static final Message SAMPLE_MESSAGE = Message.builder() - .taskId(TEST_TASK_ID) - .contextId(TEST_TASK_CONTEXT_ID) - .parts(new TextPart("Test message")) - .role(ROLE_AGENT) - .build(); - - private static final List> SAMPLE_PARTS = List.of(new TextPart("Test message")); - - private static final PushNotificationSender NOOP_PUSHNOTIFICATION_SENDER = task -> {}; - - EventQueue eventQueue; - private MainEventBus mainEventBus; - private MainEventBusProcessor mainEventBusProcessor; - private AgentEmitter agentEmitter; - - - - @BeforeEach - public void init() { - // Set up MainEventBus and processor for production-like test environment - InMemoryTaskStore taskStore = new InMemoryTaskStore(); - mainEventBus = new MainEventBus(); - InMemoryQueueManager queueManager = new InMemoryQueueManager(taskStore, mainEventBus); - mainEventBusProcessor = new MainEventBusProcessor(mainEventBus, taskStore, NOOP_PUSHNOTIFICATION_SENDER, queueManager); - EventQueueUtil.start(mainEventBusProcessor); - - eventQueue = EventQueueUtil.getEventQueueBuilder(mainEventBus) - .taskId(TEST_TASK_ID) - .mainEventBus(mainEventBus) - .build().tap(); - RequestContext context = new RequestContext.Builder() - .setTaskId(TEST_TASK_ID) - .setContextId(TEST_TASK_CONTEXT_ID) - .build(); - agentEmitter = new AgentEmitter(context, eventQueue); - } - - @AfterEach - public void cleanup() { - if (mainEventBusProcessor != null) { - EventQueueUtil.stop(mainEventBusProcessor); - } - } - - @Test - public void testAddArtifactWithCustomIdAndName() throws Exception { - agentEmitter.addArtifact(SAMPLE_PARTS, "custom-artifact-id", "Custom Artifact", null); - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event event = item.getEvent(); - assertNotNull(event); - assertInstanceOf(TaskArtifactUpdateEvent.class, event); - - TaskArtifactUpdateEvent taue = (TaskArtifactUpdateEvent) event; - assertEquals(TEST_TASK_ID, taue.taskId()); - assertEquals(TEST_TASK_CONTEXT_ID, taue.contextId()); - assertEquals("custom-artifact-id", taue.artifact().artifactId()); - assertEquals("Custom Artifact", taue.artifact().name()); - assertSame(SAMPLE_PARTS, taue.artifact().parts()); - - - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testCompleteWithoutMessage() throws Exception { - agentEmitter.complete(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, null); - } - - @Test - public void testCompleteWithMessage() throws Exception { - agentEmitter.complete(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, SAMPLE_MESSAGE); - } - - @Test - public void testSubmitWithoutMessage() throws Exception { - agentEmitter.submit(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_SUBMITTED, null); - } - - @Test - public void testSubmitWithMessage() throws Exception { - agentEmitter.submit(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_SUBMITTED, SAMPLE_MESSAGE); - } - - @Test - public void testStartWorkWithoutMessage() throws Exception { - agentEmitter.startWork(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_WORKING, null); - } - - @Test - public void testStartWorkWithMessage() throws Exception { - agentEmitter.startWork(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_WORKING, SAMPLE_MESSAGE); - } - - @Test - public void testFailedWithoutMessage() throws Exception { - agentEmitter.fail(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_FAILED, null); - } - - @Test - public void testFailedWithMessage() throws Exception { - agentEmitter.fail(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_FAILED, SAMPLE_MESSAGE); - } - - @Test - public void testCanceledWithoutMessage() throws Exception { - agentEmitter.cancel(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_CANCELED, null); - } - - @Test - public void testCanceledWithMessage() throws Exception { - agentEmitter.cancel(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_CANCELED, SAMPLE_MESSAGE); - } - - @Test - public void testRejectWithoutMessage() throws Exception { - agentEmitter.reject(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_REJECTED, null); - } - - @Test - public void testRejectWithMessage() throws Exception { - agentEmitter.reject(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_REJECTED, SAMPLE_MESSAGE); - } - - @Test - public void testRequiresInputWithoutMessage() throws Exception { - agentEmitter.requiresInput(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, null); - } - - @Test - public void testRequiresInputWithMessage() throws Exception { - agentEmitter.requiresInput(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, SAMPLE_MESSAGE); - } - - @Test - public void testRequiresInputWithFinalTrue() throws Exception { - agentEmitter.requiresInput(true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, null); - } - - @Test - public void testRequiresInputWithMessageAndFinalTrue() throws Exception { - agentEmitter.requiresInput(SAMPLE_MESSAGE, true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, SAMPLE_MESSAGE); - } - - @Test - public void testRequiresAuthWithoutMessage() throws Exception { - agentEmitter.requiresAuth(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, null); - } - - @Test - public void testRequiresAuthWithMessage() throws Exception { - agentEmitter.requiresAuth(SAMPLE_MESSAGE); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, SAMPLE_MESSAGE); - } - - @Test - public void testRequiresAuthWithFinalTrue() throws Exception { - agentEmitter.requiresAuth(true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, null); - } - - @Test - public void testRequiresAuthWithMessageAndFinalTrue() throws Exception { - agentEmitter.requiresAuth(SAMPLE_MESSAGE, true); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, SAMPLE_MESSAGE); - } - - @Test - public void testNonTerminalStateUpdatesAllowed() throws Exception { - // Non-terminal states should be allowed multiple times - agentEmitter.submit(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_SUBMITTED, null); - - agentEmitter.startWork(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_WORKING, null); - - agentEmitter.requiresInput(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_INPUT_REQUIRED, null); - - agentEmitter.requiresAuth(); - checkTaskStatusUpdateEventOnQueue(false, TaskState.TASK_STATE_AUTH_REQUIRED, null); - - // Should still be able to complete - agentEmitter.complete(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, null); - } - - @Test - public void testNewAgentMessage() throws Exception { - Message message = agentEmitter.newAgentMessage(SAMPLE_PARTS, null); - - assertEquals(ROLE_AGENT, message.role()); - assertEquals(TEST_TASK_ID, message.taskId()); - assertEquals(TEST_TASK_CONTEXT_ID, message.contextId()); - assertNotNull(message.messageId()); - assertEquals(SAMPLE_PARTS, message.parts()); - assertNull(message.metadata()); - } - - @Test - public void testNewAgentMessageWithMetadata() throws Exception { - Map metadata = Map.of("key", "value"); - Message message = agentEmitter.newAgentMessage(SAMPLE_PARTS, metadata); - - assertEquals(ROLE_AGENT, message.role()); - assertEquals(TEST_TASK_ID, message.taskId()); - assertEquals(TEST_TASK_CONTEXT_ID, message.contextId()); - assertNotNull(message.messageId()); - assertEquals(SAMPLE_PARTS, message.parts()); - assertEquals(metadata, message.metadata()); - } - - @Test - public void testAddArtifactWithAppendTrue() throws Exception { - agentEmitter.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, null); - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event event = item.getEvent(); - assertNotNull(event); - assertInstanceOf(TaskArtifactUpdateEvent.class, event); - - TaskArtifactUpdateEvent taue = (TaskArtifactUpdateEvent) event; - assertEquals(TEST_TASK_ID, taue.taskId()); - assertEquals(TEST_TASK_CONTEXT_ID, taue.contextId()); - assertEquals("artifact-id", taue.artifact().artifactId()); - assertEquals("Test Artifact", taue.artifact().name()); - assertSame(SAMPLE_PARTS, taue.artifact().parts()); - assertEquals(true, taue.append()); - assertNull(taue.lastChunk()); - - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testAddArtifactWithLastChunkTrue() throws Exception { - agentEmitter.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, null, true); - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event event = item.getEvent(); - assertNotNull(event); - assertInstanceOf(TaskArtifactUpdateEvent.class, event); - - TaskArtifactUpdateEvent taue = (TaskArtifactUpdateEvent) event; - assertEquals("artifact-id", taue.artifact().artifactId()); - assertNull(taue.append()); - assertEquals(true, taue.lastChunk()); - - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testAddArtifactWithAppendAndLastChunk() throws Exception { - agentEmitter.addArtifact(SAMPLE_PARTS, "artifact-id", "Test Artifact", null, true, false); - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event event = item.getEvent(); - assertNotNull(event); - assertInstanceOf(TaskArtifactUpdateEvent.class, event); - - TaskArtifactUpdateEvent taue = (TaskArtifactUpdateEvent) event; - assertEquals(true, taue.append()); - assertEquals(false, taue.lastChunk()); - - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testAddArtifactGeneratesIdWhenNull() throws Exception { - agentEmitter.addArtifact(SAMPLE_PARTS, null, "Test Artifact", null); - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event event = item.getEvent(); - assertNotNull(event); - assertInstanceOf(TaskArtifactUpdateEvent.class, event); - - TaskArtifactUpdateEvent taue = (TaskArtifactUpdateEvent) event; - assertNotNull(taue.artifact().artifactId()); - // Check that it's a valid UUID format - String artifactId = taue.artifact().artifactId(); - assertEquals(36, artifactId.length()); // Standard UUID length - assertTrue(artifactId.matches("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")); - - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testTerminalStateProtectionAfterComplete() throws Exception { - // Complete the task first - agentEmitter.complete(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_COMPLETED, null); - - // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.startWork()); - assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); - - // Verify no additional events were queued - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testTerminalStateProtectionAfterFail() throws Exception { - // Fail the task first - agentEmitter.fail(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_FAILED, null); - - // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.complete()); - assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); - - // Verify no additional events were queued - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testTerminalStateProtectionAfterReject() throws Exception { - // Reject the task first - agentEmitter.reject(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_REJECTED, null); - - // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.startWork()); - assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); - - // Verify no additional events were queued - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testTerminalStateProtectionAfterCancel() throws Exception { - // Cancel the task first - agentEmitter.cancel(); - checkTaskStatusUpdateEventOnQueue(true, TaskState.TASK_STATE_CANCELED, null); - - // Try to update status again - should throw RuntimeException - RuntimeException exception = assertThrows(RuntimeException.class, () -> agentEmitter.submit()); - assertEquals("Cannot update task status - terminal state already reached", exception.getMessage()); - - // Verify no additional events were queued - assertNull(eventQueue.dequeueEventItem(0)); - } - - @Test - public void testConcurrentCompletionAttempts() throws Exception { - // This test simulates race condition between multiple completion attempts - Thread thread1 = new Thread(() -> { - try { - agentEmitter.complete(); - } catch (RuntimeException e) { - // Expected for one of the threads - } - }); - - Thread thread2 = new Thread(() -> { - try { - agentEmitter.fail(); - } catch (RuntimeException e) { - // Expected for one of the threads - } - }); - - thread1.start(); - thread2.start(); - - thread1.join(); - thread2.join(); - - // Exactly one event should have been queued - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event event = item.getEvent(); - assertNotNull(event); - assertInstanceOf(TaskStatusUpdateEvent.class, event); - - TaskStatusUpdateEvent tsue = (TaskStatusUpdateEvent) event; - assertTrue(tsue.isFinal()); - assertTrue(tsue.status().state() == TaskState.TASK_STATE_COMPLETED || tsue.status().state() == TaskState.TASK_STATE_FAILED); - - // No additional events should be queued - assertNull(eventQueue.dequeueEventItem(0)); - } - - private TaskStatusUpdateEvent checkTaskStatusUpdateEventOnQueue(boolean isFinal, TaskState state, Message statusMessage) throws Exception { - // Wait up to 5 seconds for event (async MainEventBusProcessor needs time to distribute) - EventQueueItem item = eventQueue.dequeueEventItem(5000); - assertNotNull(item); - Event event = item.getEvent(); - - assertNotNull(event); - assertInstanceOf(TaskStatusUpdateEvent.class, event); - - TaskStatusUpdateEvent tsue = (TaskStatusUpdateEvent) event; - assertEquals(TEST_TASK_ID, tsue.taskId()); - assertEquals(TEST_TASK_CONTEXT_ID, tsue.contextId()); - assertEquals(isFinal, tsue.isFinal()); - assertEquals(state, tsue.status().state()); - assertEquals(statusMessage, tsue.status().message()); - - // Check no additional events (still use 0 timeout for this check) - assertNull(eventQueue.dequeueEventItem(0)); - - return tsue; - } -} diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java b/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java deleted file mode 100644 index bc96b36ac..000000000 --- a/server-common/src/test/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStoreTest.java +++ /dev/null @@ -1,624 +0,0 @@ -package io.a2a.server.tasks; - -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.util.List; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.common.A2AHeaders; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -class InMemoryPushNotificationConfigStoreTest { - - private InMemoryPushNotificationConfigStore configStore; - private BasePushNotificationSender notificationSender; - - @Mock - private A2AHttpClient mockHttpClient; - - @Mock - private A2AHttpClient.PostBuilder mockPostBuilder; - - @Mock - private A2AHttpResponse mockHttpResponse; - - @BeforeEach - public void setUp() { - MockitoAnnotations.openMocks(this); - configStore = new InMemoryPushNotificationConfigStore(); - notificationSender = new BasePushNotificationSender(configStore, mockHttpClient); - } - - private void setupBasicMockHttpResponse() throws Exception { - when(mockHttpClient.createPost()).thenReturn(mockPostBuilder); - when(mockPostBuilder.url(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.addHeader(CONTENT_TYPE, APPLICATION_JSON)).thenReturn(mockPostBuilder); - when(mockPostBuilder.body(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.post()).thenReturn(mockHttpResponse); - when(mockHttpResponse.success()).thenReturn(true); - } - - private void verifyHttpCallWithoutToken(PushNotificationConfig config, Task task, String expectedToken) throws Exception { - ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); - verify(mockHttpClient).createPost(); - verify(mockPostBuilder).url(config.url()); - verify(mockPostBuilder).body(bodyCaptor.capture()); - verify(mockPostBuilder).post(); - // Verify that addHeader was never called for authentication token - verify(mockPostBuilder, never()).addHeader(A2AHeaders.X_A2A_NOTIFICATION_TOKEN, expectedToken); - - // Verify the request body contains the task data - String sentBody = bodyCaptor.getValue(); - assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().name())); - } - - private Task createSampleTask(String taskId, TaskState state) { - return Task.builder() - .id(taskId) - .contextId("ctx456") - .status(new TaskStatus(state)) - .build(); - } - - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() - .url(url) - .id(configId) - .token(token) - .build(); - } - - @Test - public void testSetInfoAddsNewConfig() { - String taskId = "task_new"; - PushNotificationConfig config = createSamplePushConfig("http://new.url/callback", "cfg1", null); - - PushNotificationConfig result = configStore.setInfo(taskId, config); - - assertNotNull(result); - assertEquals(config.url(), result.url()); - assertEquals(config.id(), result.id()); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); - } - - @Test - public void testSetInfoAppendsToExistingConfig() { - String taskId = "task_update"; - PushNotificationConfig initialConfig = createSamplePushConfig( - "http://initial.url/callback", "cfg_initial", null); - configStore.setInfo(taskId, initialConfig); - - PushNotificationConfig updatedConfig = createSamplePushConfig( - "http://updated.url/callback", "cfg_updated", null); - configStore.setInfo(taskId, updatedConfig); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(2, configResult.configs().size()); - - // Find the configs by ID since order might vary - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); - PushNotificationConfig foundInitial = configs.stream() - .filter(c -> "cfg_initial".equals(c.id())) - .findFirst() - .orElse(null); - PushNotificationConfig foundUpdated = configs.stream() - .filter(c -> "cfg_updated".equals(c.id())) - .findFirst() - .orElse(null); - - assertNotNull(foundInitial); - assertNotNull(foundUpdated); - assertEquals(initialConfig.url(), foundInitial.url()); - assertEquals(updatedConfig.url(), foundUpdated.url()); - } - - @Test - public void testSetInfoWithoutConfigId() { - String taskId = "task1"; - PushNotificationConfig initialConfig = PushNotificationConfig.builder() - .url("http://initial.url/callback") - .build(); // No ID set - - PushNotificationConfig result = configStore.setInfo(taskId, initialConfig); - assertEquals(taskId, result.id(), "Config ID should default to taskId when not provided"); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertEquals(1, configResult.configs().size()); - assertEquals(taskId, configResult.configs().get(0).config().id()); - - PushNotificationConfig updatedConfig = PushNotificationConfig.builder() - .url("http://initial.url/callback_new") - .build(); // No ID set - - PushNotificationConfig updatedResult = configStore.setInfo(taskId, updatedConfig); - assertEquals(taskId, updatedResult.id()); - - configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertEquals(1, configResult.configs().size(), "Should replace existing config with same ID rather than adding new one"); - assertEquals(updatedConfig.url(), configResult.configs().get(0).config().url()); - } - - @Test - public void testGetInfoExistingConfig() { - String taskId = "task_get_exist"; - PushNotificationConfig config = createSamplePushConfig("http://get.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - assertEquals(config.id(), configResult.configs().get(0).config().id()); - } - - @Test - public void testGetInfoNonExistentConfig() { - String taskId = "task_get_non_exist"; - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertTrue(configResult.configs().isEmpty(), "Should return empty list for non-existent task ID"); - } - - @Test - public void testDeleteInfoExistingConfig() { - String taskId = "task_delete_exist"; - PushNotificationConfig config = createSamplePushConfig("http://delete.this/callback", "cfg1", null); - configStore.setInfo(taskId, config); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - - configStore.deleteInfo(taskId, config.id()); - - ListTaskPushNotificationConfigResult configsAfterDelete = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configsAfterDelete); - assertTrue(configsAfterDelete.configs().isEmpty(), "Should return empty list when no configs remain after deletion"); - } - - @Test - public void testDeleteInfoNonExistentConfig() { - String taskId = "task_delete_non_exist"; - // Should not throw an error - configStore.deleteInfo(taskId, "non_existent_id"); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertTrue(configResult.configs().isEmpty(), "Should return empty list for non-existent task ID"); - } - - @Test - public void testDeleteInfoWithNullConfigId() { - String taskId = "task_delete_null_config"; - PushNotificationConfig config = PushNotificationConfig.builder() - .url("http://delete.this/callback") - .build(); // No ID set, will use taskId - configStore.setInfo(taskId, config); - - // Delete with null configId should use taskId - configStore.deleteInfo(taskId, null); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertTrue(configResult.configs().isEmpty(), "Should return empty list after deletion when using taskId as configId"); - } - - @Test - public void testSendNotificationSuccess() throws Exception { - String taskId = "task_send_success"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - configStore.setInfo(taskId, config); - - // Mock successful HTTP response - setupBasicMockHttpResponse(); - - notificationSender.sendNotification(task); - - // Verify HTTP client was called - ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); - verify(mockHttpClient).createPost(); - verify(mockPostBuilder).url(config.url()); - verify(mockPostBuilder).body(bodyCaptor.capture()); - verify(mockPostBuilder).post(); - - // Verify the request body contains the task data - String sentBody = bodyCaptor.getValue(); - assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().name())); - } - - @Test - public void testSendNotificationWithToken() throws Exception { - String taskId = "task_send_with_token"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); - configStore.setInfo(taskId, config); - - // Mock successful HTTP response - when(mockHttpClient.createPost()).thenReturn(mockPostBuilder); - when(mockPostBuilder.url(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.body(any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.addHeader(any(String.class), any(String.class))).thenReturn(mockPostBuilder); - when(mockPostBuilder.post()).thenReturn(mockHttpResponse); - when(mockHttpResponse.success()).thenReturn(true); - - notificationSender.sendNotification(task); - - // Verify HTTP client was called with proper authentication - ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); - verify(mockHttpClient).createPost(); - verify(mockPostBuilder).url(config.url()); - verify(mockPostBuilder).body(bodyCaptor.capture()); - // Verify that the token is included in request headers as X-A2A-Notification-Token - verify(mockPostBuilder).addHeader(A2AHeaders.X_A2A_NOTIFICATION_TOKEN, config.token()); - verify(mockPostBuilder).post(); - - // Verify the request body contains the task data - String sentBody = bodyCaptor.getValue(); - assertTrue(sentBody.contains(task.id())); - assertTrue(sentBody.contains(task.status().state().name())); - } - - @Test - public void testSendNotificationNoConfig() throws Exception { - String taskId = "task_send_no_config"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - - notificationSender.sendNotification(task); - - // Verify HTTP client was never called - verify(mockHttpClient, never()).createPost(); - } - - @Test - public void testSendNotificationWithEmptyToken() throws Exception { - String taskId = "task_send_empty_token"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", ""); - configStore.setInfo(taskId, config); - - setupBasicMockHttpResponse(); - notificationSender.sendNotification(task); - verifyHttpCallWithoutToken(config, task, ""); - } - - @Test - public void testSendNotificationWithBlankToken() throws Exception { - String taskId = "task_send_blank_token"; - Task task = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", " "); - configStore.setInfo(taskId, config); - - setupBasicMockHttpResponse(); - notificationSender.sendNotification(task); - verifyHttpCallWithoutToken(config, task, " "); - } - - @Test - public void testMultipleConfigsForSameTask() { - String taskId = "task_multiple"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); - - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(2, configResult.configs().size()); - - // Verify both configs are present - List configs = configResult.configs().stream() - .map(TaskPushNotificationConfig::config) - .toList(); - assertTrue(configs.stream().anyMatch(c -> "cfg1".equals(c.id()))); - assertTrue(configs.stream().anyMatch(c -> "cfg2".equals(c.id()))); - } - - @Test - public void testDeleteSpecificConfigFromMultiple() { - String taskId = "task_delete_specific"; - PushNotificationConfig config1 = createSamplePushConfig("http://url1.com/callback", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://url2.com/callback", "cfg2", null); - - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); - - // Delete only config1 - configStore.deleteInfo(taskId, "cfg1"); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(configResult); - assertEquals(1, configResult.configs().size()); - assertEquals("cfg2", configResult.configs().get(0).config().id()); - } - - @Test - public void testConfigStoreIntegration() { - String taskId = "integration_test"; - PushNotificationConfig config = createSamplePushConfig("http://example.com", "test_id", "test_token"); - - // Test that we can store and retrieve configurations - PushNotificationConfig storedConfig = configStore.setInfo(taskId, config); - assertEquals(config.url(), storedConfig.url()); - assertEquals(config.token(), storedConfig.token()); - - ListTaskPushNotificationConfigResult configResult = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertEquals(1, configResult.configs().size()); - assertEquals(config.url(), configResult.configs().get(0).config().url()); - - // Test deletion - configStore.deleteInfo(taskId, storedConfig.id()); - ListTaskPushNotificationConfigResult afterDeletion = configStore.getInfo(new ListTaskPushNotificationConfigParams(taskId)); - assertNotNull(afterDeletion); - assertTrue(afterDeletion.configs().isEmpty()); - } - - @Test - public void testPaginationWithPageSize() { - String taskId = "task_pagination"; - // Create 5 configs - for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Request first page with pageSize=2 - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - assertNotNull(result); - assertEquals(2, result.configs().size(), "Should return 2 configs"); - assertNotNull(result.nextPageToken(), "Should have nextPageToken when more items exist"); - } - - @Test - public void testPaginationWithPageToken() { - String taskId = "task_pagination_token"; - // Create 5 configs - for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Get first page - ListTaskPushNotificationConfigParams firstPageParams = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult firstPage = configStore.getInfo(firstPageParams); - assertNotNull(firstPage.nextPageToken()); - - // Get second page using nextPageToken - ListTaskPushNotificationConfigParams secondPageParams = new ListTaskPushNotificationConfigParams( - taskId, 2, firstPage.nextPageToken(), ""); - ListTaskPushNotificationConfigResult secondPage = configStore.getInfo(secondPageParams); - - assertNotNull(secondPage); - assertEquals(2, secondPage.configs().size(), "Should return 2 configs for second page"); - assertNotNull(secondPage.nextPageToken(), "Should have nextPageToken when more items exist"); - - // Verify NO overlap between pages - collect all IDs from both pages - List firstPageIds = firstPage.configs().stream() - .map(c -> c.config().id()) - .toList(); - List secondPageIds = secondPage.configs().stream() - .map(c -> c.config().id()) - .toList(); - - // Check that no ID from first page appears in second page - for (String id : firstPageIds) { - assertTrue(!secondPageIds.contains(id), - "Config " + id + " appears in both pages - overlap detected!"); - } - - // Also verify the pages are sequential (first page ends before second page starts) - // Since configs are created in order, we can verify the IDs - assertEquals("cfg0", firstPageIds.get(0)); - assertEquals("cfg1", firstPageIds.get(1)); - assertEquals("cfg2", secondPageIds.get(0)); - assertEquals("cfg3", secondPageIds.get(1)); - } - - @Test - public void testPaginationLastPage() { - String taskId = "task_pagination_last"; - // Create 5 configs - for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Get first page (2 items) - ListTaskPushNotificationConfigParams firstPageParams = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult firstPage = configStore.getInfo(firstPageParams); - - // Get second page (2 items) - ListTaskPushNotificationConfigParams secondPageParams = new ListTaskPushNotificationConfigParams( - taskId, 2, firstPage.nextPageToken(), ""); - ListTaskPushNotificationConfigResult secondPage = configStore.getInfo(secondPageParams); - - // Get last page (1 item remaining) - ListTaskPushNotificationConfigParams lastPageParams = new ListTaskPushNotificationConfigParams( - taskId, 2, secondPage.nextPageToken(), ""); - ListTaskPushNotificationConfigResult lastPage = configStore.getInfo(lastPageParams); - - assertNotNull(lastPage); - assertEquals(1, lastPage.configs().size(), "Last page should have 1 remaining config"); - assertNull(lastPage.nextPageToken(), "Last page should not have nextPageToken"); - } - - @Test - public void testPaginationWithZeroPageSize() { - String taskId = "task_pagination_zero"; - // Create 5 configs - for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Request with pageSize=0 should return all configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 0, "", ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - assertNotNull(result); - assertEquals(5, result.configs().size(), "Should return all 5 configs when pageSize=0"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when returning all"); - } - - @Test - public void testPaginationWithNegativePageSize() { - String taskId = "task_pagination_negative"; - // Create 3 configs - for (int i = 0; i < 3; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Request with negative pageSize should return all configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, -1, "", ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - assertNotNull(result); - assertEquals(3, result.configs().size(), "Should return all configs when pageSize is negative"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when returning all"); - } - - @Test - public void testPaginationPageSizeLargerThanConfigs() { - String taskId = "task_pagination_large"; - // Create 3 configs - for (int i = 0; i < 3; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Request with pageSize larger than available configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 10, "", ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - assertNotNull(result); - assertEquals(3, result.configs().size(), "Should return all 3 configs"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when all configs fit in one page"); - } - - @Test - public void testPaginationExactlyPageSize() { - String taskId = "task_pagination_exact"; - // Create exactly 3 configs - for (int i = 0; i < 3; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Request with pageSize equal to number of configs - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 3, "", ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - assertNotNull(result); - assertEquals(3, result.configs().size(), "Should return all 3 configs"); - assertNull(result.nextPageToken(), "Should not have nextPageToken when configs exactly match pageSize"); - } - - @Test - public void testPaginationWithInvalidToken() { - String taskId = "task_pagination_invalid_token"; - // Create 5 configs - for (int i = 0; i < 5; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Request with invalid pageToken - implementation behavior is to start from beginning - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams( - taskId, 2, "invalid_token_that_does_not_exist", ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - assertNotNull(result); - // When token is not found, implementation starts from beginning - assertEquals(2, result.configs().size(), "Should return first page when token is not found"); - assertNotNull(result.nextPageToken(), "Should have nextPageToken since more items exist"); - } - - @Test - public void testPaginationEmptyTaskWithPageSize() { - String taskId = "task_pagination_empty"; - // No configs created - - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 2, "", ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - assertNotNull(result); - assertTrue(result.configs().isEmpty(), "Should return empty list for non-existent task"); - assertNull(result.nextPageToken(), "Should not have nextPageToken for empty result"); - } - - @Test - public void testPaginationFullIteration() { - String taskId = "task_pagination_full"; - // Create 7 configs - for (int i = 0; i < 7; i++) { - PushNotificationConfig config = createSamplePushConfig( - "http://url" + i + ".com/callback", "cfg" + i, "token" + i); - configStore.setInfo(taskId, config); - } - - // Iterate through all pages with pageSize=3 - int totalCollected = 0; - String pageToken = ""; - int pageCount = 0; - - do { - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, 3, pageToken, ""); - ListTaskPushNotificationConfigResult result = configStore.getInfo(params); - - totalCollected += result.configs().size(); - pageToken = result.nextPageToken(); - pageCount++; - - // Safety check to prevent infinite loop - assertTrue(pageCount <= 10, "Should not have more than 10 pages for 7 configs"); - - } while (pageToken != null); - - assertEquals(7, totalCollected, "Should collect all 7 configs across all pages"); - assertEquals(3, pageCount, "Should have exactly 3 pages (3+3+1)"); - } - -} diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java b/server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java deleted file mode 100644 index e69de29bb..000000000 diff --git a/server-common/src/test/java/io/a2a/server/tasks/MockTaskStateProvider.java b/server-common/src/test/java/io/a2a/server/tasks/MockTaskStateProvider.java deleted file mode 100644 index c14ad1628..000000000 --- a/server-common/src/test/java/io/a2a/server/tasks/MockTaskStateProvider.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.a2a.server.tasks; - -import java.util.HashSet; -import java.util.Set; - -/** - * Mock implementation of TaskStateProvider for testing. - * Allows tests to explicitly control which tasks are considered finalized. - */ -public class MockTaskStateProvider implements TaskStateProvider { - private final Set finalizedTasks = new HashSet<>(); - - /** - * Mark a task as finalized for testing purposes. - * - * @param taskId the task ID to mark as finalized - */ - public void markFinalized(String taskId) { - finalizedTasks.add(taskId); - } - - /** - * Unmark a task as finalized (return to active state). - * - * @param taskId the task ID to unmark - */ - public void unmarkFinalized(String taskId) { - finalizedTasks.remove(taskId); - } - - @Override - public boolean isTaskActive(String taskId) { - return !finalizedTasks.contains(taskId); - } - - @Override - public boolean isTaskFinalized(String taskId) { - return finalizedTasks.contains(taskId); - } -} diff --git a/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java b/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java deleted file mode 100644 index 4a68d849a..000000000 --- a/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java +++ /dev/null @@ -1,451 +0,0 @@ -package io.a2a.server.tasks; - -import static io.a2a.client.http.A2AHttpClient.APPLICATION_JSON; -import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.common.A2AHeaders; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class PushNotificationSenderTest { - - private TestHttpClient testHttpClient; - private InMemoryPushNotificationConfigStore configStore; - private BasePushNotificationSender sender; - - /** - * Simple test implementation of A2AHttpClient that captures HTTP calls for verification. - * Now captures StreamingEventKind events wrapped in StreamResponse format. - */ - private static class TestHttpClient implements A2AHttpClient { - final List events = Collections.synchronizedList(new ArrayList<>()); - final List urls = Collections.synchronizedList(new ArrayList<>()); - final List> headers = Collections.synchronizedList(new ArrayList<>()); - final List rawBodies = Collections.synchronizedList(new ArrayList<>()); - volatile CountDownLatch latch; - volatile boolean shouldThrowException = false; - - @Override - public GetBuilder createGet() { - return null; - } - - @Override - public PostBuilder createPost() { - return new TestPostBuilder(); - } - - @Override - public DeleteBuilder createDelete() { - return null; - } - - class TestPostBuilder implements A2AHttpClient.PostBuilder { - private volatile String body; - private volatile String url; - private final Map requestHeaders = new java.util.HashMap<>(); - - @Override - public PostBuilder body(String body) { - this.body = body; - return this; - } - - @Override - public A2AHttpResponse post() throws IOException, InterruptedException { - if (shouldThrowException) { - throw new IOException("Simulated network error"); - } - - try { - // Store raw body for verification - rawBodies.add(body); - - // Parse StreamResponse format to extract the event - // The body contains a wrapper with one of: task, message, statusUpdate, artifactUpdate - StreamingEventKind event = JsonUtil.fromJson(body, StreamingEventKind.class); - events.add(event); - urls.add(url); - headers.add(new java.util.HashMap<>(requestHeaders)); - - return new A2AHttpResponse() { - @Override - public int status() { - return 200; - } - - @Override - public boolean success() { - return true; - } - - @Override - public String body() { - return ""; - } - }; - } catch (JsonProcessingException e) { - throw new IOException("Failed to parse StreamingEventKind JSON", e); - } finally { - if (latch != null) { - latch.countDown(); - } - } - } - - @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { - return null; - } - - @Override - public PostBuilder url(String url) { - this.url = url; - return this; - } - - @Override - public PostBuilder addHeader(String name, String value) { - requestHeaders.put(name, value); - return this; - } - - @Override - public PostBuilder addHeaders(Map headers) { - requestHeaders.putAll(headers); - return this; - } - } - } - - @BeforeEach - public void setUp() { - testHttpClient = new TestHttpClient(); - configStore = new InMemoryPushNotificationConfigStore(); - sender = new BasePushNotificationSender(configStore, testHttpClient); - } - - private void testSendNotificationWithInvalidToken(String token, String testName) throws InterruptedException { - String taskId = testName; - Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", token); - - // Set up the configuration in the store - configStore.setInfo(taskId, config); - - // Set up latch to wait for async completion - testHttpClient.latch = new CountDownLatch(1); - - sender.sendNotification(taskData); - - // Wait for the async operation to complete - assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the task was sent via HTTP wrapped in StreamResponse format - assertEquals(1, testHttpClient.events.size()); - StreamingEventKind sentEvent = testHttpClient.events.get(0); - assertTrue(sentEvent instanceof Task, "Event should be a Task"); - Task sentTask = (Task) sentEvent; - assertEquals(taskData.id(), sentTask.id()); - - // Verify that no authentication header was sent (invalid token should not add header) - assertEquals(1, testHttpClient.headers.size()); - Map sentHeaders = testHttpClient.headers.get(0); - assertEquals(1, sentHeaders.size()); - assertFalse(sentHeaders.containsKey(A2AHeaders.X_A2A_NOTIFICATION_TOKEN), - "X-A2A-Notification-Token header should not be sent when token is invalid"); - // Content-Type header should always be present - assertTrue(sentHeaders.containsKey(CONTENT_TYPE)); - assertEquals(APPLICATION_JSON, sentHeaders.get(CONTENT_TYPE)); - } - - private Task createSampleTask(String taskId, TaskState state) { - return Task.builder() - .id(taskId) - .contextId("ctx456") - .status(new TaskStatus(state)) - .build(); - } - - private PushNotificationConfig createSamplePushConfig(String url, String configId, String token) { - return PushNotificationConfig.builder() - .url(url) - .id(configId) - .token(token) - .build(); - } - - @Test - public void testSendNotificationSuccess() throws InterruptedException { - String taskId = "task_send_success"; - Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - - // Set up the configuration in the store - configStore.setInfo(taskId, config); - - // Set up latch to wait for async completion - testHttpClient.latch = new CountDownLatch(1); - - sender.sendNotification(taskData); - - // Wait for the async operation to complete - assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the task was sent via HTTP wrapped in StreamResponse format - assertEquals(1, testHttpClient.events.size()); - StreamingEventKind sentEvent = testHttpClient.events.get(0); - assertTrue(sentEvent instanceof Task, "Event should be a Task"); - Task sentTask = (Task) sentEvent; - assertEquals(taskData.id(), sentTask.id()); - assertEquals(taskData.contextId(), sentTask.contextId()); - assertEquals(taskData.status().state(), sentTask.status().state()); - - // Verify StreamResponse wrapper is present in raw body - String rawBody = testHttpClient.rawBodies.get(0); - assertTrue(rawBody.contains("\"task\""), "Raw body should contain 'task' discriminator for StreamResponse"); - } - - @Test - public void testSendNotificationWithTokenSuccess() throws InterruptedException { - String taskId = "task_send_with_token"; - Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", "unique_token"); - - // Set up the configuration in the store - configStore.setInfo(taskId, config); - - // Set up latch to wait for async completion - testHttpClient.latch = new CountDownLatch(1); - - sender.sendNotification(taskData); - - // Wait for the async operation to complete - assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the task was sent via HTTP wrapped in StreamResponse format - assertEquals(1, testHttpClient.events.size()); - StreamingEventKind sentEvent = testHttpClient.events.get(0); - assertTrue(sentEvent instanceof Task, "Event should be a Task"); - Task sentTask = (Task) sentEvent; - assertEquals(taskData.id(), sentTask.id()); - - // Verify that the X-A2A-Notification-Token header is sent with the correct token - assertEquals(1, testHttpClient.headers.size()); - Map sentHeaders = testHttpClient.headers.get(0); - assertEquals(2, sentHeaders.size()); - assertTrue(sentHeaders.containsKey(A2AHeaders.X_A2A_NOTIFICATION_TOKEN)); - assertEquals(config.token(), sentHeaders.get(A2AHeaders.X_A2A_NOTIFICATION_TOKEN)); - // Content-Type header should always be present - assertTrue(sentHeaders.containsKey(CONTENT_TYPE)); - assertEquals(APPLICATION_JSON, sentHeaders.get(CONTENT_TYPE)); - - } - - @Test - public void testSendNotificationNoConfig() { - String taskId = "task_send_no_config"; - Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - - // Don't set any configuration in the store - sender.sendNotification(taskData); - - // Verify no HTTP calls were made - assertEquals(0, testHttpClient.events.size()); - } - - @Test - public void testSendNotificationWithEmptyToken() throws InterruptedException { - testSendNotificationWithInvalidToken("", "task_send_empty_token"); - } - - @Test - public void testSendNotificationWithBlankToken() throws InterruptedException { - testSendNotificationWithInvalidToken(" ", "task_send_blank_token"); - } - - @Test - public void testSendNotificationMultipleConfigs() throws InterruptedException { - String taskId = "task_multiple_configs"; - Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config1 = createSamplePushConfig("http://notify.me/cfg1", "cfg1", null); - PushNotificationConfig config2 = createSamplePushConfig("http://notify.me/cfg2", "cfg2", null); - - // Set up multiple configurations in the store - configStore.setInfo(taskId, config1); - configStore.setInfo(taskId, config2); - - // Set up latch to wait for async completion (2 calls expected) - testHttpClient.latch = new CountDownLatch(2); - - sender.sendNotification(taskData); - - // Wait for the async operations to complete - assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP calls should complete within 5 seconds"); - - // Verify both events were sent via HTTP wrapped in StreamResponse format - assertEquals(2, testHttpClient.events.size()); - assertEquals(2, testHttpClient.urls.size()); - assertTrue(testHttpClient.urls.containsAll(java.util.List.of("http://notify.me/cfg1", "http://notify.me/cfg2"))); - - // Both events should be identical (same event sent to different endpoints) - for (StreamingEventKind sentEvent : testHttpClient.events) { - assertTrue(sentEvent instanceof Task, "Event should be a Task"); - Task sentTask = (Task) sentEvent; - assertEquals(taskData.id(), sentTask.id()); - assertEquals(taskData.contextId(), sentTask.contextId()); - assertEquals(taskData.status().state(), sentTask.status().state()); - } - } - - @Test - public void testSendNotificationHttpError() { - String taskId = "task_send_http_err"; - Task taskData = createSampleTask(taskId, TaskState.TASK_STATE_COMPLETED); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/http_error", "cfg1", null); - - // Set up the configuration in the store - configStore.setInfo(taskId, config); - - // Configure the test client to throw an exception - testHttpClient.shouldThrowException = true; - - // This should not throw an exception - errors should be handled gracefully - sender.sendNotification(taskData); - - // Verify no events were successfully processed due to the error - assertEquals(0, testHttpClient.events.size()); - } - - @Test - public void testSendNotificationMessage() throws InterruptedException { - String taskId = "task_send_message"; - Message message = Message.builder() - .taskId(taskId) - .role(Message.Role.ROLE_AGENT) - .parts(new TextPart("Hello from agent")) - .build(); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - - // Set up the configuration in the store - configStore.setInfo(taskId, config); - - // Set up latch to wait for async completion - testHttpClient.latch = new CountDownLatch(1); - - sender.sendNotification(message); - - // Wait for the async operation to complete - assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the message was sent via HTTP wrapped in StreamResponse format - assertEquals(1, testHttpClient.events.size()); - StreamingEventKind sentEvent = testHttpClient.events.get(0); - assertTrue(sentEvent instanceof Message, "Event should be a Message"); - Message sentMessage = (Message) sentEvent; - assertEquals(taskId, sentMessage.taskId()); - - // Verify StreamResponse wrapper with 'message' discriminator - String rawBody = testHttpClient.rawBodies.get(0); - assertTrue(rawBody.contains("\"message\""), "Raw body should contain 'message' discriminator for StreamResponse"); - } - - @Test - public void testSendNotificationTaskStatusUpdate() throws InterruptedException { - String taskId = "task_send_status_update"; - TaskStatusUpdateEvent statusUpdate = TaskStatusUpdateEvent.builder() - .taskId(taskId) - .contextId("ctx456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - - // Set up the configuration in the store - configStore.setInfo(taskId, config); - - // Set up latch to wait for async completion - testHttpClient.latch = new CountDownLatch(1); - - sender.sendNotification(statusUpdate); - - // Wait for the async operation to complete - assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the status update was sent via HTTP wrapped in StreamResponse format - assertEquals(1, testHttpClient.events.size()); - StreamingEventKind sentEvent = testHttpClient.events.get(0); - assertTrue(sentEvent instanceof TaskStatusUpdateEvent, "Event should be a TaskStatusUpdateEvent"); - TaskStatusUpdateEvent sentUpdate = (TaskStatusUpdateEvent) sentEvent; - assertEquals(taskId, sentUpdate.taskId()); - assertEquals(TaskState.TASK_STATE_WORKING, sentUpdate.status().state()); - - // Verify StreamResponse wrapper with 'statusUpdate' discriminator - String rawBody = testHttpClient.rawBodies.get(0); - assertTrue(rawBody.contains("\"statusUpdate\""), "Raw body should contain 'statusUpdate' discriminator for StreamResponse"); - } - - @Test - public void testSendNotificationTaskArtifactUpdate() throws InterruptedException { - String taskId = "task_send_artifact_update"; - Artifact artifact = Artifact.builder() - .artifactId("artifact-1") - .name("test-artifact") - .parts(Collections.singletonList(new TextPart("Artifact chunk"))) - .build(); - TaskArtifactUpdateEvent artifactUpdate = TaskArtifactUpdateEvent.builder() - .taskId(taskId) - .contextId("ctx456") - .artifact(artifact) - .build(); - PushNotificationConfig config = createSamplePushConfig("http://notify.me/here", "cfg1", null); - - // Set up the configuration in the store - configStore.setInfo(taskId, config); - - // Set up latch to wait for async completion - testHttpClient.latch = new CountDownLatch(1); - - sender.sendNotification(artifactUpdate); - - // Wait for the async operation to complete - assertTrue(testHttpClient.latch.await(5, TimeUnit.SECONDS), "HTTP call should complete within 5 seconds"); - - // Verify the artifact update was sent via HTTP wrapped in StreamResponse format - assertEquals(1, testHttpClient.events.size()); - StreamingEventKind sentEvent = testHttpClient.events.get(0); - assertTrue(sentEvent instanceof TaskArtifactUpdateEvent, "Event should be a TaskArtifactUpdateEvent"); - TaskArtifactUpdateEvent sentUpdate = (TaskArtifactUpdateEvent) sentEvent; - assertEquals(taskId, sentUpdate.taskId()); - - // Verify StreamResponse wrapper with 'artifactUpdate' discriminator - String rawBody = testHttpClient.rawBodies.get(0); - assertTrue(rawBody.contains("\"artifactUpdate\""), "Raw body should contain 'artifactUpdate' discriminator for StreamResponse"); - } -} diff --git a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java b/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java deleted file mode 100644 index fa4eb8ef5..000000000 --- a/server-common/src/test/java/io/a2a/server/tasks/ResultAggregatorTest.java +++ /dev/null @@ -1,281 +0,0 @@ -package io.a2a.server.tasks; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.atMost; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import java.util.Collections; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import io.a2a.server.events.EventConsumer; -import io.a2a.server.events.EventQueue; -import io.a2a.server.events.EventQueueUtil; -import io.a2a.server.events.InMemoryQueueManager; -import io.a2a.server.events.MainEventBus; -import io.a2a.server.events.MainEventBusProcessor; -import io.a2a.spec.Event; -import io.a2a.spec.EventKind; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TextPart; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Comprehensive tests for ResultAggregator based on Python test patterns. - * This is not a strict backport of the Python test, but it implements the same testing patterns - * adapted for Java's reactive streams and concurrency model. - * - * Note: This simplified version focuses on the core functionality without complex reactive stream testing - * that was causing issues with the original implementation. - */ -public class ResultAggregatorTest { - - @Mock - private TaskManager mockTaskManager; - - private ResultAggregator aggregator; - // Use a real thread pool executor instead of direct executor - // to avoid blocking the calling thread during async operations - private final Executor testExecutor = Executors.newCachedThreadPool(); - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - aggregator = new ResultAggregator(mockTaskManager, null, testExecutor, testExecutor); - } - - // Helper methods for creating sample data - private Message createSampleMessage(String content, String msgId, Message.Role role) { - return Message.builder() - .messageId(msgId) - .role(role) - .parts(Collections.singletonList(new TextPart(content))) - .build(); - } - - private Task createSampleTask(String taskId, TaskState statusState, String contextId) { - return Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(statusState)) - .build(); - } - - /** - * Helper to wait for MainEventBusProcessor to process an event. - * Replaces polling patterns with deterministic callback-based waiting. - * - * @param processor the processor to set callback on - * @param action the action that triggers event processing - * @throws InterruptedException if waiting is interrupted - * @throws AssertionError if processing doesn't complete within timeout - */ - private void waitForEventProcessing(MainEventBusProcessor processor, Runnable action) throws InterruptedException { - CountDownLatch processingLatch = new CountDownLatch(1); - processor.setCallback(new io.a2a.server.events.MainEventBusProcessorCallback() { - @Override - public void onEventProcessed(String taskId, Event event) { - processingLatch.countDown(); - } - - @Override - public void onTaskFinalized(String taskId) { - // Not needed for basic event processing wait - } - }); - - try { - action.run(); - assertTrue(processingLatch.await(5, TimeUnit.SECONDS), - "MainEventBusProcessor should have processed the event within timeout"); - } finally { - processor.setCallback(null); - } - } - - - // Basic functionality tests - - @Test - void testConstructorWithMessage() { - Message initialMessage = createSampleMessage("initial", "msg1", Message.Role.ROLE_USER); - ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, initialMessage, testExecutor, testExecutor); - - // Test that the message is properly stored by checking getCurrentResult - assertEquals(initialMessage, aggregatorWithMessage.getCurrentResult()); - // TaskManager should not be called when message is set - verifyNoInteractions(mockTaskManager); - } - - @Test - void testGetCurrentResultWithMessageSet() { - Message sampleMessage = createSampleMessage("hola", "msg1", Message.Role.ROLE_USER); - ResultAggregator aggregatorWithMessage = new ResultAggregator(mockTaskManager, sampleMessage, testExecutor, testExecutor); - - EventKind result = aggregatorWithMessage.getCurrentResult(); - - assertEquals(sampleMessage, result); - // TaskManager.getTask() should not be called when message is set - verifyNoInteractions(mockTaskManager); - } - - @Test - void testGetCurrentResultWithMessageNull() { - Task expectedTask = createSampleTask("task_from_tm", TaskState.TASK_STATE_SUBMITTED, "ctx1"); - when(mockTaskManager.getTask()).thenReturn(expectedTask); - - EventKind result = aggregator.getCurrentResult(); - - assertEquals(expectedTask, result); - verify(mockTaskManager).getTask(); - } - - @Test - void testConstructorStoresTaskManagerCorrectly() { - // Test that constructor properly initializes the aggregator - // We can't access the private field directly, but we can test behavior - Task expectedTask = createSampleTask("test_task", TaskState.TASK_STATE_SUBMITTED, "ctx1"); - when(mockTaskManager.getTask()).thenReturn(expectedTask); - - EventKind result = aggregator.getCurrentResult(); - - assertEquals(expectedTask, result); - verify(mockTaskManager).getTask(); - } - - @Test - void testConstructorWithNullMessage() { - ResultAggregator aggregatorWithNullMessage = new ResultAggregator(mockTaskManager, null, testExecutor, testExecutor); - Task expectedTask = createSampleTask("null_msg_task", TaskState.TASK_STATE_WORKING, "ctx1"); - when(mockTaskManager.getTask()).thenReturn(expectedTask); - - EventKind result = aggregatorWithNullMessage.getCurrentResult(); - - assertEquals(expectedTask, result); - verify(mockTaskManager).getTask(); - } - - @Test - void testGetCurrentResultReturnsTaskWhenNoMessage() { - Task expectedTask = createSampleTask("no_message_task", TaskState.TASK_STATE_COMPLETED, "ctx1"); - when(mockTaskManager.getTask()).thenReturn(expectedTask); - - EventKind result = aggregator.getCurrentResult(); - - assertNotNull(result); - assertEquals(expectedTask, result); - verify(mockTaskManager).getTask(); - } - - @Test - void testGetCurrentResultWithDifferentTaskStates() { - // Test with WORKING and COMPLETED states using chained returns - Task workingTask = createSampleTask("working_task", TaskState.TASK_STATE_WORKING, "ctx1"); - Task completedTask = createSampleTask("completed_task", TaskState.TASK_STATE_COMPLETED, "ctx1"); - when(mockTaskManager.getTask()).thenReturn(workingTask, completedTask); - - // First call returns WORKING task - EventKind result1 = aggregator.getCurrentResult(); - assertEquals(workingTask, result1); - - // Second call returns COMPLETED task - EventKind result2 = aggregator.getCurrentResult(); - assertEquals(completedTask, result2); - } - - @Test - void testMultipleGetCurrentResultCalls() { - // Test that multiple calls to getCurrentResult behave consistently - Task expectedTask = createSampleTask("multi_call_task", TaskState.TASK_STATE_SUBMITTED, "ctx1"); - when(mockTaskManager.getTask()).thenReturn(expectedTask); - - EventKind result1 = aggregator.getCurrentResult(); - EventKind result2 = aggregator.getCurrentResult(); - EventKind result3 = aggregator.getCurrentResult(); - - assertEquals(expectedTask, result1); - assertEquals(expectedTask, result2); - assertEquals(expectedTask, result3); - - // Verify getTask was called multiple times - verify(mockTaskManager, times(3)).getTask(); - } - - @Test - void testGetCurrentResultWithMessageTakesPrecedence() { - // Test that when both message and task are available, message takes precedence - Message message = createSampleMessage("priority message", "pri1", Message.Role.ROLE_USER); - ResultAggregator messageAggregator = new ResultAggregator(mockTaskManager, message, testExecutor, testExecutor); - - // Even if we set up the task manager to return something, message should take precedence - Task task = createSampleTask("should_not_be_returned", TaskState.TASK_STATE_WORKING, "ctx1"); - when(mockTaskManager.getTask()).thenReturn(task); - - EventKind result = messageAggregator.getCurrentResult(); - - assertEquals(message, result); - // Task manager should not be called when message is present - verifyNoInteractions(mockTaskManager); - } - - @Test - void testConsumeAndBreakNonBlocking() throws Exception { - // Test that with blocking=false, the method returns after the first event - String taskId = "test-task"; - Task firstEvent = createSampleTask(taskId, TaskState.TASK_STATE_WORKING, "ctx1"); - - // After processing firstEvent, the current result will be that task - when(mockTaskManager.getTask()).thenReturn(firstEvent); - - // Create an event queue using QueueManager (which has access to builder) - MainEventBus mainEventBus = new MainEventBus(); - InMemoryTaskStore taskStore = new InMemoryTaskStore(); - InMemoryQueueManager queueManager = - new InMemoryQueueManager(new MockTaskStateProvider(), mainEventBus); - MainEventBusProcessor processor = new MainEventBusProcessor(mainEventBus, taskStore, task -> {}, queueManager); - EventQueueUtil.start(processor); - - EventQueue queue = queueManager.getEventQueueBuilder(taskId).build().tap(); - - // Use callback to wait for event processing (replaces polling) - waitForEventProcessing(processor, () -> queue.enqueueEvent(firstEvent)); - - // Create real EventConsumer with the queue - EventConsumer eventConsumer = - new EventConsumer(queue); - - // Close queue after first event to simulate stream ending after processing - queue.close(); - - ResultAggregator.EventTypeAndInterrupt result = - aggregator.consumeAndBreakOnInterrupt(eventConsumer, false); - - assertEquals(firstEvent, result.eventType()); - assertTrue(result.interrupted()); - // NOTE: ResultAggregator no longer calls taskManager.process() - // That responsibility has moved to MainEventBusProcessor for centralized persistence - // - // NOTE: Since firstEvent is a Task, ResultAggregator captures it directly from the queue - // (capturedTask.get() at line 283 in ResultAggregator). Therefore, taskManager.getTask() - // is only called for debug logging in taskIdForLogging() (line 305), which may or may not - // execute depending on timing and log level. We expect 0-1 calls, not 1-2. - verify(mockTaskManager, atMost(1)).getTask(); - - // Cleanup: stop the processor - EventQueueUtil.stop(processor); - } -} diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java b/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java deleted file mode 100644 index 0c502fd3a..000000000 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java +++ /dev/null @@ -1,745 +0,0 @@ -package io.a2a.server.tasks; - -import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.spec.A2AServerException; -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class TaskManagerTest { - private static final String TASK_JSON = """ - { - "id": "task-abc", - "contextId" : "session-xyz", - "status": {"state": "TASK_STATE_SUBMITTED"} - }"""; - - Task minimalTask; - TaskStore taskStore; - TaskManager taskManager; - - @BeforeEach - public void init() throws Exception { - minimalTask = fromJson(TASK_JSON, Task.class); - taskStore = new InMemoryTaskStore(); - taskManager = new TaskManager(minimalTask.id(), minimalTask.contextId(), taskStore, null); - } - - @Test - public void testGetTaskExisting() { - Task expectedTask = minimalTask; - taskStore.save(expectedTask, false); - Task retrieved = taskManager.getTask(); - assertSame(expectedTask, retrieved); - } - - @Test - public void testGetTaskNonExistent() { - Task retrieved = taskManager.getTask(); - assertNull(retrieved); - } - - @Test - public void testSaveTaskEventNewTask() throws A2AServerException { - taskManager.saveTaskEvent(minimalTask, false); - Task saved = taskManager.getTask(); - Task retrieved = taskManager.getTask(); - assertSame(minimalTask, retrieved); - } - - @Test - public void testSaveTaskEventStatusUpdate() throws A2AServerException { - Task initialTask = minimalTask; - taskStore.save(initialTask, false); - - TaskStatus newStatus = new TaskStatus( - TaskState.TASK_STATE_WORKING, - Message.builder() - .role(Message.Role.ROLE_AGENT) - .parts(Collections.singletonList(new TextPart("content"))) - .messageId("messageId") - .build(), - null); - TaskStatusUpdateEvent event = new TaskStatusUpdateEvent( - minimalTask.id(), - newStatus, - minimalTask.contextId(), - false, - new HashMap<>()); - - - taskManager.saveTaskEvent(event, false); - Task saved = taskManager.getTask(); - Task updated = taskManager.getTask(); - - assertNotSame(initialTask, updated); - - assertEquals(initialTask.id(), updated.id()); - assertEquals(initialTask.contextId(), updated.contextId()); - // TODO type does not get unmarshalled - //assertEquals(initialTask.getType(), updated.getType()); - assertSame(newStatus, updated.status()); - } - - @Test - public void testSaveTaskEventArtifactUpdate() throws A2AServerException { - Task initialTask = minimalTask; - Artifact newArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("content"))) - .build(); - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(newArtifact) - .build(); - taskManager.saveTaskEvent(event, false); - Task saved = taskManager.getTask(); - - Task updatedTask = taskManager.getTask(); - - assertNotSame(initialTask, updatedTask); - assertEquals(initialTask.id(), updatedTask.id()); - assertEquals(initialTask.contextId(), updatedTask.contextId()); - assertSame(initialTask.status().state(), updatedTask.status().state()); - assertEquals(1, updatedTask.artifacts().size()); - assertEquals(newArtifact, updatedTask.artifacts().get(0)); - } - - @Test - public void testEnsureTaskExisting() { - // This tests the 'working case' of the internal logic to check a task being updated existas - // We are already testing that - } - - @Test - public void testEnsureTaskNonExistentForStatusUpdate() throws A2AServerException { - // Tests that an update event instantiates a new task and that - TaskManager taskManagerWithoutId = new TaskManager(null, null, taskStore, null); - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("new-task") - .contextId("some-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - taskManagerWithoutId.saveTaskEvent(event, false); - Task task = taskManagerWithoutId.getTask(); - assertEquals(event.taskId(), taskManagerWithoutId.getTaskId()); - assertEquals(event.contextId(), taskManagerWithoutId.getContextId()); - - Task newTask = taskManagerWithoutId.getTask(); - assertEquals(event.taskId(), newTask.id()); - assertEquals(event.contextId(), newTask.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, newTask.status().state()); - assertSame(newTask, task); - } - - @Test - public void testSaveTaskEventNewTaskNoTaskId() throws A2AServerException { - TaskManager taskManagerWithoutId = new TaskManager(null, null, taskStore, null); - Task task = Task.builder() - .id("new-task-id") - .contextId("some-context") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - taskManagerWithoutId.saveTaskEvent(task, false); - Task saved = taskManager.getTask(); - assertEquals(task.id(), taskManagerWithoutId.getTaskId()); - assertEquals(task.contextId(), taskManagerWithoutId.getContextId()); - - Task retrieved = taskManagerWithoutId.getTask(); - assertSame(task, retrieved); - } - - @Test - public void testGetTaskNoTaskId() { - TaskManager taskManagerWithoutId = new TaskManager(null, null, taskStore, null); - Task retrieved = taskManagerWithoutId.getTask(); - assertNull(retrieved); - } - - // Additional tests for missing coverage scenarios - - @Test - public void testTaskArtifactUpdateEventAppendTrueWithExistingArtifact() throws A2AServerException { - // Setup: Create a task with an existing artifact - Task initialTask = minimalTask; - Artifact existingArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("existing content"))) - .metadata(Map.of("key1", "value1")) - .build(); - Task taskWithArtifact = Task.builder(initialTask) - .artifacts(Collections.singletonList(existingArtifact)) - .build(); - taskStore.save(taskWithArtifact, false); - - // Test: Append new parts to existing artifact - Artifact newArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("new content"))) - .metadata(Map.of("key2", "value2")) - .build(); - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(newArtifact) - .append(true) - .build(); - - taskManager.saveTaskEvent(event, false); - Task updatedTask = taskManager.getTask(); - - assertEquals(1, updatedTask.artifacts().size()); - Artifact updatedArtifact = updatedTask.artifacts().get(0); - assertEquals("artifact-id", updatedArtifact.artifactId()); - assertEquals(2, updatedArtifact.parts().size()); - assertEquals("existing content", ((TextPart) updatedArtifact.parts().get(0)).text()); - assertEquals("new content", ((TextPart) updatedArtifact.parts().get(1)).text()); - - assertEquals("value1", updatedArtifact.metadata().get("key1")); - assertEquals("value2", updatedArtifact.metadata().get("key2")); - } - - @Test - public void testTaskArtifactUpdateEventAppendTrueWithoutExistingArtifact() throws A2AServerException { - // Setup: Create a task without artifacts - Task initialTask = minimalTask; - taskStore.save(initialTask, false); - - // Test: Try to append to non-existent artifact (should be ignored) - Artifact newArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("new content"))) - .build(); - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(newArtifact) - .append(true) - .build(); - - taskManager.saveTaskEvent(event, false); - Task saved = taskManager.getTask(); - Task updatedTask = taskManager.getTask(); - - // Should have no artifacts since append was ignored - assertEquals(0, updatedTask.artifacts().size()); - } - - @Test - public void testTaskArtifactUpdateEventAppendFalseWithExistingArtifact() throws A2AServerException { - // Setup: Create a task with an existing artifact - Task initialTask = minimalTask; - Artifact existingArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("existing content"))) - .build(); - Task taskWithArtifact = Task.builder(initialTask) - .artifacts(Collections.singletonList(existingArtifact)) - .build(); - taskStore.save(taskWithArtifact, false); - - // Test: Replace existing artifact (append=false) - Artifact newArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("replacement content"))) - .build(); - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(newArtifact) - .append(false) - .build(); - - taskManager.saveTaskEvent(event, false); - Task saved = taskManager.getTask(); - Task updatedTask = taskManager.getTask(); - - assertEquals(1, updatedTask.artifacts().size()); - Artifact updatedArtifact = updatedTask.artifacts().get(0); - assertEquals("artifact-id", updatedArtifact.artifactId()); - assertEquals(1, updatedArtifact.parts().size()); - assertEquals("replacement content", ((TextPart) updatedArtifact.parts().get(0)).text()); - } - - @Test - public void testTaskArtifactUpdateEventAppendNullWithExistingArtifact() throws A2AServerException { - // Setup: Create a task with an existing artifact - Task initialTask = minimalTask; - Artifact existingArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("existing content"))) - .build(); - Task taskWithArtifact = Task.builder(initialTask) - .artifacts(Collections.singletonList(existingArtifact)) - .build(); - taskStore.save(taskWithArtifact, false); - - // Test: Replace existing artifact (append=null, defaults to false) - Artifact newArtifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("replacement content"))) - .build(); - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(newArtifact) - .build(); // append is null - - taskManager.saveTaskEvent(event, false); - Task saved = taskManager.getTask(); - Task updatedTask = taskManager.getTask(); - - assertEquals(1, updatedTask.artifacts().size()); - Artifact updatedArtifact = updatedTask.artifacts().get(0); - assertEquals("artifact-id", updatedArtifact.artifactId()); - assertEquals(1, updatedArtifact.parts().size()); - assertEquals("replacement content", ((TextPart) updatedArtifact.parts().get(0)).text()); - } - - @Test - public void testAddingTaskWithDifferentIdFails() { - // Test that adding a task with a different id from the taskmanager's taskId fails - TaskManager taskManagerWithId = new TaskManager("task-abc", "session-xyz", taskStore, null); - - Task differentTask = Task.builder() - .id("different-task-id") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - assertThrows(A2AServerException.class, () -> { - taskManagerWithId.saveTaskEvent(differentTask, false); - }); - } - - @Test - public void testAddingTaskWithDifferentIdViaStatusUpdateFails() { - // Test that adding a status update with different taskId fails - TaskManager taskManagerWithId = new TaskManager("task-abc", "session-xyz", taskStore, null); - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("different-task-id") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - assertThrows(A2AServerException.class, () -> { - taskManagerWithId.saveTaskEvent(event, false); - }); - } - - @Test - public void testAddingTaskWithDifferentIdViaArtifactUpdateFails() { - // Test that adding an artifact update with different taskId fails - TaskManager taskManagerWithId = new TaskManager("task-abc", "session-xyz", taskStore, null); - - Artifact artifact = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("content"))) - .build(); - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId("different-task-id") - .contextId("session-xyz") - .artifact(artifact) - .build(); - - assertThrows(A2AServerException.class, () -> { - taskManagerWithId.saveTaskEvent(event, false); - }); - } - - @Test - public void testTaskWithNoMessageUsesInitialMessage() throws A2AServerException { - // Test that adding a task with no message, and there is a TaskManager.initialMessage, - // the initialMessage gets used - Message initialMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("initial message"))) - .messageId("initial-msg-id") - .build(); - - TaskManager taskManagerWithInitialMessage = new TaskManager(null, null, taskStore, initialMessage); - - // Use a status update event instead of a Task to trigger createTask - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("new-task-id") - .contextId("some-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - taskManagerWithInitialMessage.saveTaskEvent(event, false); - Task saved = taskManager.getTask(); - Task retrieved = taskManagerWithInitialMessage.getTask(); - - // Check that the task has the initial message in its history - assertNotNull(retrieved.history()); - assertEquals(1, retrieved.history().size()); - Message historyMessage = retrieved.history().get(0); - assertEquals(initialMessage.messageId(), historyMessage.messageId()); - assertEquals(initialMessage.role(), historyMessage.role()); - assertEquals("initial message", ((TextPart) historyMessage.parts().get(0)).text()); - } - - @Test - public void testTaskWithMessageDoesNotUseInitialMessage() throws A2AServerException { - // Test that adding a task with a message does not use the initial message - Message initialMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("initial message"))) - .messageId("initial-msg-id") - .build(); - - TaskManager taskManagerWithInitialMessage = new TaskManager(null, null, taskStore, initialMessage); - - Message taskMessage = Message.builder() - .role(Message.Role.ROLE_AGENT) - .parts(Collections.singletonList(new TextPart("task message"))) - .messageId("task-msg-id") - .build(); - - // Use TaskStatusUpdateEvent to trigger the creation of a task, which will check if the initialMessage is used. - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("new-task-id") - .contextId("some-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, taskMessage, null)) - .build(); - - taskManagerWithInitialMessage.saveTaskEvent(event, false); - Task saved = taskManager.getTask(); - Task retrieved = taskManagerWithInitialMessage.getTask(); - - // There should now be a history containing the initialMessage - // But the current message (taskMessage) should be in the state, not in the history - assertNotNull(retrieved.history()); - assertEquals(1, retrieved.history().size()); - assertEquals("initial message", ((TextPart) retrieved.history().get(0).parts().get(0)).text()); - - // The message in the current state should be taskMessage - assertNotNull(retrieved.status().message()); - assertEquals("task message", ((TextPart) retrieved.status().message().parts().get(0)).text()); - } - - @Test - public void testMultipleArtifactsWithSameArtifactId() throws A2AServerException { - // Test handling of multiple artifacts with the same artifactId - Task initialTask = minimalTask; - taskStore.save(initialTask, false); - - // Add first artifact - Artifact artifact1 = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("content 1"))) - .build(); - TaskArtifactUpdateEvent event1 = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(artifact1) - .build(); - taskManager.saveTaskEvent(event1, false); - - // Add second artifact with same artifactId (should replace the first) - Artifact artifact2 = Artifact.builder() - .artifactId("artifact-id") - .name("artifact-2") - .parts(Collections.singletonList(new TextPart("content 2"))) - .build(); - TaskArtifactUpdateEvent event2 = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(artifact2) - .build(); - taskManager.saveTaskEvent(event2, false); - - Task updatedTask = taskManager.getTask(); - assertEquals(1, updatedTask.artifacts().size()); - Artifact finalArtifact = updatedTask.artifacts().get(0); - assertEquals("artifact-id", finalArtifact.artifactId()); - assertEquals("artifact-2", finalArtifact.name()); - assertEquals("content 2", ((TextPart) finalArtifact.parts().get(0)).text()); - } - - @Test - public void testMultipleArtifactsWithDifferentArtifactIds() throws A2AServerException { - // Test handling of multiple artifacts with different artifactIds - Task initialTask = minimalTask; - taskStore.save(initialTask, false); - - // Add first artifact - Artifact artifact1 = Artifact.builder() - .artifactId("artifact-id-1") - .name("artifact-1") - .parts(Collections.singletonList(new TextPart("content 1"))) - .build(); - TaskArtifactUpdateEvent event1 = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(artifact1) - .build(); - taskManager.saveTaskEvent(event1, false); - - // Add second artifact with different artifactId (should be added) - Artifact artifact2 = Artifact.builder() - .artifactId("artifact-id-2") - .name("artifact-2") - .parts(Collections.singletonList(new TextPart("content 2"))) - .build(); - TaskArtifactUpdateEvent event2 = TaskArtifactUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .artifact(artifact2) - .build(); - taskManager.saveTaskEvent(event2, false); - - Task updatedTask = taskManager.getTask(); - assertEquals(2, updatedTask.artifacts().size()); - - // Verify both artifacts are present - List artifacts = updatedTask.artifacts(); - assertTrue(artifacts.stream() - .anyMatch(a -> "artifact-id-1".equals(a.artifactId()) - && "content 1".equals(((TextPart) a.parts().get(0)).text())) - , "Artifact 1 should be present"); - assertTrue(artifacts.stream() - .anyMatch(a -> "artifact-id-2".equals(a.artifactId()) - && "content 2".equals(((TextPart) a.parts().get(0)).text())) - , "Artifact 2 should be present"); - } - - @Test - public void testInvalidTaskIdValidation() { - // Test that creating TaskManager with null taskId is allowed (Python allows None) - TaskManager taskManagerWithNullId = new TaskManager(null, "context", taskStore, null); - assertNull(taskManagerWithNullId.getTaskId()); - - // Test that empty string task ID is handled (Java doesn't have explicit validation like Python) - TaskManager taskManagerWithEmptyId = new TaskManager("", "context", taskStore, null); - assertEquals("", taskManagerWithEmptyId.getTaskId()); - } - - @Test - public void testSaveTaskEventMetadataUpdate() throws A2AServerException { - // Test that metadata from TaskStatusUpdateEvent gets saved to the task - Task initialTask = minimalTask; - taskStore.save(initialTask, false); - - Map newMetadata = new HashMap<>(); - newMetadata.put("meta_key_test", "meta_value_test"); - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .metadata(newMetadata) - .build(); - - taskManager.saveTaskEvent(event, false); - - Task updatedTask = taskManager.getTask(); - assertEquals(newMetadata, updatedTask.metadata()); - } - - @Test - public void testSaveTaskEventMetadataUpdateNull() throws A2AServerException { - // Test that null metadata in TaskStatusUpdateEvent doesn't affect task - Task initialTask = minimalTask; - taskStore.save(initialTask, false); - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .metadata(null) - .build(); - - taskManager.saveTaskEvent(event, false); - - Task updatedTask = taskManager.getTask(); - // Should preserve original task's metadata (which is likely null for minimal task) - assertNull(updatedTask.metadata()); - } - - @Test - public void testSaveTaskEventMetadataMergeExisting() throws A2AServerException { - // Test that metadata update merges with existing metadata - Map originalMetadata = new HashMap<>(); - originalMetadata.put("original_key", "original_value"); - - Task taskWithMetadata = Task.builder(minimalTask) - .metadata(originalMetadata) - .build(); - taskStore.save(taskWithMetadata, false); - - Map newMetadata = new HashMap<>(); - newMetadata.put("new_key", "new_value"); - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId(minimalTask.id()) - .contextId(minimalTask.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .metadata(newMetadata) - .build(); - - taskManager.saveTaskEvent(event, false); - - Task updatedTask = taskManager.getTask(); - - Map mergedMetadata = new HashMap<>(originalMetadata); - mergedMetadata.putAll(newMetadata); - assertEquals(mergedMetadata, updatedTask.metadata()); - } - - @Test - public void testCreateTaskWithInitialMessage() throws A2AServerException { - // Test equivalent of _init_task_obj functionality - Message initialMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("initial message"))) - .messageId("initial-msg-id") - .build(); - - TaskManager taskManagerWithMessage = new TaskManager(null, null, taskStore, initialMessage); - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("new-task-id") - .contextId("some-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - taskManagerWithMessage.saveTaskEvent(event, false); - Task savedTask = taskManagerWithMessage.getTask(); - - // Verify task was created properly - assertNotNull(savedTask); - assertEquals("new-task-id", savedTask.id()); - assertEquals("some-context", savedTask.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, savedTask.status().state()); - - // Verify initial message is in history - assertNotNull(savedTask.history()); - assertEquals(1, savedTask.history().size()); - Message historyMessage = savedTask.history().get(0); - assertEquals("initial-msg-id", historyMessage.messageId()); - assertEquals("initial message", ((TextPart) historyMessage.parts().get(0)).text()); - } - - @Test - public void testCreateTaskWithoutInitialMessage() throws A2AServerException { - // Test task creation without initial message - TaskManager taskManagerWithoutMessage = new TaskManager(null, null, taskStore, null); - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("new-task-id") - .contextId("some-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - taskManagerWithoutMessage.saveTaskEvent(event, false); - Task savedTask = taskManagerWithoutMessage.getTask(); - - // Verify task was created properly - assertNotNull(savedTask); - assertEquals("new-task-id", savedTask.id()); - assertEquals("some-context", savedTask.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, savedTask.status().state()); - - // Verify no history since there was no initial message - assertTrue(savedTask.history().isEmpty()); - } - - @Test - public void testSaveTaskInternal() throws A2AServerException { - // Test equivalent of _save_task functionality through saveTaskEvent - TaskManager taskManagerWithoutId = new TaskManager(null, null, taskStore, null); - - Task newTask = Task.builder() - .id("test-task-id") - .contextId("test-context") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - taskManagerWithoutId.saveTaskEvent(newTask, false); - Task savedTask = taskManagerWithoutId.getTask(); - - // Verify internal state was updated - assertEquals("test-task-id", taskManagerWithoutId.getTaskId()); - assertEquals("test-context", taskManagerWithoutId.getContextId()); - assertSame(savedTask, taskManagerWithoutId.getTask()); - } - - @Test - public void testUpdateWithMessage() throws A2AServerException { - Message initialMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("initial message"))) - .messageId("initial-msg-id") - .build(); - - TaskManager taskManagerWithInitialMessage = new TaskManager(null, null, taskStore, initialMessage); - - Message taskMessage = Message.builder() - .role(Message.Role.ROLE_AGENT) - .parts(Collections.singletonList(new TextPart("task message"))) - .messageId("task-msg-id") - .build(); - - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("new-task-id") - .contextId("some-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED, taskMessage, null)) - .build(); - - taskManagerWithInitialMessage.saveTaskEvent(event, false); - Task saved = taskManagerWithInitialMessage.getTask(); - - Message updateMessage = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("update message"))) - .messageId("update-msg-id") - .build(); - - Task updated = taskManagerWithInitialMessage.updateWithMessage(updateMessage, saved); - - // There should now be a history containing the initialMessage, task message and update message - assertNotNull(updated.history()); - assertEquals(3, updated.history().size()); - assertEquals("initial message", ((TextPart) updated.history().get(0).parts().get(0)).text()); - - // The message in the current state should be null - assertNull(updated.status().message()); - assertEquals("task message", ((TextPart) updated.history().get(1).parts().get(0)).text()); - assertEquals("update message", ((TextPart) updated.history().get(2).parts().get(0)).text()); - } -} diff --git a/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java b/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java deleted file mode 100644 index 34912efe6..000000000 --- a/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java +++ /dev/null @@ -1,153 +0,0 @@ -package io.a2a.server.util; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import io.a2a.spec.Artifact; -import io.a2a.spec.DataPart; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; -class ArtifactUtilsTest { - - @Test - void testNewArtifactAssignsPartsNameDescription() { - // Given - List> parts = List.of(new TextPart("Sample text")); - String name = "My Artifact"; - String description = "This is a test artifact."; - - // When - Artifact artifact = ArtifactUtils.newArtifact(name, parts, description); - - // Then - assertEquals(parts, artifact.parts()); - assertEquals(name, artifact.name()); - assertEquals(description, artifact.description()); - - // Then - assertNotNull(artifact.artifactId()); - assertFalse(artifact.artifactId().isBlank()); - assertDoesNotThrow(() -> UUID.fromString(artifact.artifactId())); - } - - @Test - void testNewArtifactEmptyDescriptionIfNotProvided() { - // Given - List> parts = List.of(new TextPart("Another sample")); - String name = "Artifact_No_Desc"; - - // When - Artifact artifact = ArtifactUtils.newArtifact(name, parts); - - // Then - assertEquals(null, artifact.description()); } - - @Test - void testNewTextArtifactCreatesSingleTextPart() { - // Given - String text = "This is a text artifact."; - String name = "Text_Artifact"; - - // When - Artifact artifact = ArtifactUtils.newTextArtifact(name, text); - - // Then - assertEquals(1, artifact.parts().size()); - assertInstanceOf(TextPart.class, artifact.parts().get(0)); - } - - @Test - void testNewTextArtifactPartContainsProvidedText() { - // Given - String text = "Hello, world!"; - String name = "Greeting_Artifact"; - - // When - Artifact artifact = ArtifactUtils.newTextArtifact(name, text); - - // Then - TextPart textPart = (TextPart) artifact.parts().get(0); - assertEquals(text, textPart.text()); - } - - @Test - void testNewTextArtifactAssignsNameDescription() { - // Given - String text = "Some content."; - String name = "Named_Text_Artifact"; - String description = "Description for text artifact."; - - // When - Artifact artifact = ArtifactUtils.newTextArtifact(name, text, description); - - // Then - assertEquals(name, artifact.name()); - assertEquals(description, artifact.description()); - } - - @Test - void testNewDataArtifactCreatesSingleDataPart() { - // Given - Map sampleData = Map.of("key", "value", "number", 123); - String name = "Data_Artifact"; - - // When - Artifact artifact = ArtifactUtils.newDataArtifact(name, sampleData); - - // Then - assertEquals(1, artifact.parts().size()); - assertInstanceOf(DataPart.class, artifact.parts().get(0)); - } - - @Test - void testNewDataArtifactPartContainsProvidedData() { - // Given - Map sampleData = Map.of("content", "test_data", "is_valid", true); - String name = "Structured_Data_Artifact"; - - // When - Artifact artifact = ArtifactUtils.newDataArtifact(name, sampleData); - - // Then - DataPart dataPart = (DataPart) artifact.parts().get(0); - assertEquals(sampleData, dataPart.data()); - } - - @Test - void testNewDataArtifactAssignsNameDescription() { - // Given - Map sampleData = Map.of("info", "some details"); - String name = "Named_Data_Artifact"; - String description = "Description for data artifact."; - - // When - Artifact artifact = ArtifactUtils.newDataArtifact(name, sampleData, description); - - // Then - assertEquals(name, artifact.name()); - assertEquals(description, artifact.description()); - } - - @Test - void testArtifactIdIsNotNull() { - // Given - List> parts = List.of(new TextPart("Test")); - String name = "Test_Artifact"; - - // When - Artifact artifact = ArtifactUtils.newArtifact(name, parts); - - // Then - assertNotNull(artifact.artifactId()); - assertTrue(artifact.artifactId().length() > 0); - } -} diff --git a/server-common/src/test/java/io/a2a/server/util/async/AsyncUtilsTest.java b/server-common/src/test/java/io/a2a/server/util/async/AsyncUtilsTest.java deleted file mode 100644 index a1ac722b9..000000000 --- a/server-common/src/test/java/io/a2a/server/util/async/AsyncUtilsTest.java +++ /dev/null @@ -1,694 +0,0 @@ -package io.a2a.server.util.async; - -import static io.a2a.server.util.async.AsyncUtils.consumer; -import static io.a2a.server.util.async.AsyncUtils.convertingProcessor; -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; -import static io.a2a.server.util.async.AsyncUtils.processor; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Flow; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; -import java.util.function.Consumer; - -import mutiny.zero.ZeroPublisher; -import org.junit.jupiter.api.Test; - -public class AsyncUtilsTest { - - @Test - public void testConsumer() throws Exception { - List toSend = List.of("A", "B", "C"); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - AtomicReference error = new AtomicReference<>(); - consumer(createTubeConfig(), - publisher, - s -> { - received.add(s); - latch.countDown(); - return true; - }, - error::set); - - - latch.await(2, TimeUnit.SECONDS); - assertEquals(toSend, received); - assertNull(error.get()); - } - - @Test - public void testCancelConsumer() throws Exception { - List toSend = List.of("A", "B", "C", "D"); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - AtomicReference error = new AtomicReference<>(); - consumer(createTubeConfig(), - publisher, - s -> { - latch.countDown(); - if (s.equals("C")) { - return false; - } - received.add(s); - return true; - }, - error::set); - - Thread.sleep(500); - assertEquals(toSend.subList(0, 2), received); - assertNull(error.get()); - } - - @Test - public void testErrorConsumer() throws Exception { - List toSend = List.of("A", "B", "C", "D"); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - AtomicReference error = new AtomicReference<>(); - consumer(createTubeConfig(), - publisher, - s -> { - latch.countDown(); - if (s.equals("C")) { - throw new IllegalStateException(); - } - received.add(s); - return true; - }, - error::set); - - Thread.sleep(500); - assertEquals(toSend.subList(0, 2), received); - assertInstanceOf(IllegalStateException.class, error.get()); - } - - @Test - public void testProcessor() throws Exception { - List toSend = List.of("A", "B", "C"); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - List processed = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - Flow.Publisher processedPublisher = - processor(createTubeConfig(), publisher, (errorConsumer, s) -> { - processed.add(s); - latch.countDown(); - return true; - }); - - processedPublisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - assertEquals(toSend, received); - assertEquals(toSend, processed); - } - - @Test - public void testErrorProcessor() throws Exception { - List toSend = List.of("A", "B", "C", "D"); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - AtomicReference error = new AtomicReference<>(); - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - - Flow.Publisher processedPublisher = - processor(createTubeConfig(), publisher, (errorConsumer, s) -> { - latch.countDown(); - if (s.equals("C")) { - errorConsumer.accept(new IllegalStateException()); - } - return true; - }); - - processedPublisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - Thread.sleep(500); - assertEquals(toSend.subList(0, 2), received); - assertNotNull(error.get()); - } - - @Test - public void testUncaughtErrorProcessor() throws Exception { - List toSend = List.of("A", "B", "C", "D"); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - AtomicReference error = new AtomicReference<>(); - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - - Flow.Publisher processedPublisher = - processor(createTubeConfig(), publisher, (errorConsumer, s) -> { - latch.countDown(); - if (s.equals("C")) { - throw new IllegalStateException(); - } - return true; - }); - - processedPublisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - Thread.sleep(500); - assertEquals(toSend.subList(0, 2), received); - assertNotNull(error.get()); - } - - @Test - public void testConvertingProcessor() throws Exception { - List toSend = List.of(1, 2, 3); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - Flow.Publisher convertingPublisher = - convertingProcessor(publisher, String::valueOf); - - convertingPublisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - assertEquals(toSend.stream().map(String::valueOf).toList(), received); - } - - @Test - public void testChainedConvertingProcessors() throws Exception { - List toSend = List.of(1, 2, 3); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - Flow.Publisher convertingPublisher = - convertingProcessor(publisher, String::valueOf); - Flow.Publisher convertingPublisher2 = - convertingProcessor(convertingPublisher, Long::valueOf); - - convertingPublisher2.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(Long item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - assertEquals(toSend.stream().map(Long::valueOf).toList(), received); - } - - @Test - public void testErrorConvertingProcessor() throws Exception { - List toSend = List.of(1, 2, 3, 4); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(2); - - Flow.Publisher convertingPublisher = - convertingProcessor(publisher, i -> { - if (i == 3) { - throw new IllegalStateException(); - } - return String.valueOf(i); - }); - - convertingPublisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - assertEquals(toSend.stream().map(String::valueOf).toList().subList(0, 2), received); - } - - @Test - public void testConvertingAndProcessingProcessor() throws Exception { - List toSend = List.of(1, 2, 3); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - List processed = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - Flow.Publisher processedPublisher = - processor(createTubeConfig(), publisher, (errorConsumer, i) -> { - processed.add(i); - return true; - }); - - Flow.Publisher convertingPublisher = - convertingProcessor(processedPublisher, String::valueOf); - - convertingPublisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - latch.await(2, TimeUnit.SECONDS); - assertEquals(toSend, processed); - assertEquals(toSend.stream().map(String::valueOf).toList(), received); - } - - @Test - public void testCancelProcessor() throws Exception { - List toSend = List.of("A", "B", "C", "D"); - Flow.Publisher publisher = ZeroPublisher.fromIterable(toSend); - - List received = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); - - Flow.Publisher processedPublisher = - processor(createTubeConfig(), publisher, (errorConsumer, s) -> { - latch.countDown(); - if (s.equals("C")) { - return false; - } - return true; - }); - - processedPublisher.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - subscription.request(1); - received.add(item); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - Thread.sleep(500); - assertEquals(toSend.subList(0, 2), received); - } - - @Test - public void testMutinyZeroErrorPropagationSanityTest() { - Flow.Publisher source = ZeroPublisher.fromItems("a", "b", "c"); - - Flow.Publisher processor = ZeroPublisher.create(createTubeConfig(), tube -> { - source.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - if (item.equals("c")) { - onError(new IllegalStateException()); - } - tube.send(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - tube.fail(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - tube.complete(); - } - }); - }); - - Flow.Publisher processor2 = ZeroPublisher.create(createTubeConfig(), tube -> { - processor.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - tube.send(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - tube.fail(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - tube.complete(); - } - }); - }); - - List results = new ArrayList<>(); - - processor2.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - results.add(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - } - }); - - assertEquals(3, results.size()); - assertEquals("a", results.get(0)); - assertEquals("b", results.get(1)); - assertInstanceOf(IllegalStateException.class, results.get(2)); - } - - @Test - public void testAsyncUtilsErrorPropagation() { - Flow.Publisher source = ZeroPublisher.fromItems("a", "b", "c"); - - Flow.Publisher processor = processor(createTubeConfig(), source, new BiFunction, String, Boolean>() { - @Override - public Boolean apply(Consumer throwableConsumer, String item) { - if (item.equals("c")) { - throw new IllegalStateException(); - } - return true; - } - }); - - Flow.Publisher processor2 = processor(createTubeConfig(), processor, new BiFunction, String, Boolean>() { - @Override - public Boolean apply(Consumer throwableConsumer, String s) { - return true; - } - }); - - Flow.Publisher> processor3 = convertingProcessor(processor2, List::of); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - consumer(createTubeConfig(), - processor3, - results::add, - t -> { - results.add(t); - error.set(t); - }); - - assertEquals(3, results.size()); - assertEquals(List.of("a"), results.get(0)); - assertEquals(List.of("b"), results.get(1)); - assertInstanceOf(IllegalStateException.class, results.get(2)); - assertInstanceOf(IllegalStateException.class, error.get()); - } - - @Test - public void testMutinyZeroEventPropagationSanity() throws Exception { - Flow.Publisher source = ZeroPublisher.fromItems("one", "two", "three"); - - CountDownLatch latch = new CountDownLatch(3); - - final List results = Collections.synchronizedList(new ArrayList<>()); - - source.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - results.add(item); - subscription.request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - source.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(String item) { - results.add(item); - subscription.request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(2, TimeUnit.SECONDS); - assertEquals(6, results.size()); - } - -} diff --git a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java b/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java deleted file mode 100644 index 8156fad4c..000000000 --- a/server-common/src/test/java/io/a2a/server/version/A2AVersionValidatorTest.java +++ /dev/null @@ -1,167 +0,0 @@ -package io.a2a.server.version; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; - -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.VersionNotSupportedError; -import org.junit.jupiter.api.Test; - -public class A2AVersionValidatorTest { - - @Test - public void testIsVersionCompatible_SameMajorMinor() { - assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "1.0")); - } - - @Test - public void testIsVersionCompatible_SameMajorDifferentMinor() { - // Major versions match, minor versions can differ - assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "1.1")); - assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.1"), "1.0")); - assertTrue(A2AVersionValidator.isVersionCompatible(List.of("1.5"), "1.9")); - } - - @Test - public void testIsVersionCompatible_DifferentMajor() { - // Major versions must match exactly - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "2.0")); - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("2.0"), "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.5"), "2.5")); - } - - @Test - public void testIsVersionCompatible_InvalidFormat() { - // Invalid version formats should return false - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "invalid")); - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("invalid"), "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1"), "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), "")); - assertFalse(A2AVersionValidator.isVersionCompatible(List.of(""), "1.0")); - assertFalse(A2AVersionValidator.isVersionCompatible(List.of("1.0"), null)); - assertFalse(A2AVersionValidator.isVersionCompatible(null, "1.0")); - } - - @Test - public void testValidateProtocolVersion_NoVersionProvided_DefaultsTo1_0() { - // When no version is provided, should default to 1.0 and succeed - AgentCard agentCard = createAgentCard("1.0"); - ServerCallContext context = createContext(null); - - // Should not throw - defaults to 1.0 which matches - assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - } - - @Test - public void testValidateProtocolVersion_EmptyVersionProvided_DefaultsTo1_0() { - // When empty version is provided, should default to 1.0 and succeed - AgentCard agentCard = createAgentCard("1.0"); - ServerCallContext context = createContext(""); - - // Should not throw - defaults to 1.0 which matches - assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - } - - @Test - public void testValidateProtocolVersion_MatchingVersion() { - // When version matches exactly, should succeed - AgentCard agentCard = createAgentCard("1.0"); - ServerCallContext context = createContext("1.0"); - - // Should not throw - versions match - assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - } - - @Test - public void testValidateProtocolVersion_CompatibleMinorVersions() { - // When major version matches but minor differs, should succeed - AgentCard agentCard = createAgentCard("1.0"); - ServerCallContext context = createContext("1.1"); - - // Should not throw - same major version - assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - } - - @Test - public void testValidateProtocolVersion_CompatibleMinorVersions_Reverse() { - // When major version matches but minor differs (reverse), should succeed - AgentCard agentCard = createAgentCard("1.1"); - ServerCallContext context = createContext("1.0"); - - // Should not throw - same major version - assertDoesNotThrow(() -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - } - - @Test - public void testValidateProtocolVersion_IncompatibleMajorVersion() { - // When major version differs, should throw VersionNotSupportedError - AgentCard agentCard = createAgentCard("1.0"); - ServerCallContext context = createContext("2.0"); - - VersionNotSupportedError error = assertThrows(VersionNotSupportedError.class, - () -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - - assertTrue(error.getMessage().contains("2.0")); - assertTrue(error.getMessage().contains("1.0")); - assertTrue(error.getMessage().contains("not supported")); - } - - @Test - public void testValidateProtocolVersion_IncompatibleMajorVersion_Reverse() { - // When major version differs (reverse), should throw VersionNotSupportedError - AgentCard agentCard = createAgentCard("2.0"); - ServerCallContext context = createContext("1.0"); - - VersionNotSupportedError error = assertThrows(VersionNotSupportedError.class, - () -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - - assertTrue(error.getMessage().contains("1.0")); - assertTrue(error.getMessage().contains("2.0")); - assertTrue(error.getMessage().contains("not supported")); - } - - @Test - public void testValidateProtocolVersion_InvalidVersionFormat() { - // When invalid version is provided, should throw VersionNotSupportedError - AgentCard agentCard = createAgentCard("1.0"); - ServerCallContext context = createContext("invalid"); - - VersionNotSupportedError error = assertThrows(VersionNotSupportedError.class, - () -> A2AVersionValidator.validateProtocolVersion(agentCard, context)); - - assertTrue(error.getMessage().contains("invalid")); - assertTrue(error.getMessage().contains("not supported")); - } - - private AgentCard createAgentCard(String protocolVersion) { - return AgentCard.builder() - .name("test-card") - .description("Test card") - .supportedInterfaces(List.of(new AgentInterface("GRPC", "http://localhost:9999", "", protocolVersion))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(false) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(Collections.emptyList()) - .build(); - } - - private ServerCallContext createContext(String requestedProtocolVersion) { - return new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Collections.emptyMap(), - new HashSet<>(), - requestedProtocolVersion - ); - } -} diff --git a/server-common/src/test/resources/logback.xml b/server-common/src/test/resources/logback.xml deleted file mode 100644 index 08ac961d8..000000000 --- a/server-common/src/test/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n - - - - - - - - diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml deleted file mode 100644 index 2aaaf8760..000000000 --- a/spec-grpc/pom.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - a2a-java-sdk-spec-grpc - - jar - - Java SDK A2A Spec: gRPC - Java SDK for the Agent2Agent Protocol (A2A) - Spec: gRPC - - true - - - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - - - com.google.protobuf - protobuf-java - - - io.grpc - grpc-protobuf - provided - - - io.grpc - grpc-stub - provided - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - com.google.api.grpc - proto-google-common-protos - - - - - - org.mapstruct - mapstruct - provided - - - javax.annotation - javax.annotation-api - provided - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - com.google.protobuf - protobuf-java-util - provided - - - - - - - - io.github.ascopes - protobuf-maven-plugin - 4.1.2 - - ${skip.protobuf.generate} - true - ${protobuf-java.version} - ${project.basedir}/src/main/java/ - - - io.grpc - protoc-gen-grpc-java - ${grpc.version} - - - - - - generate-sources - - generate - - - - - - - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java b/spec-grpc/src/main/java/io/a2a/grpc/A2A.java deleted file mode 100644 index 7b1286314..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2A.java +++ /dev/null @@ -1,898 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public final class A2A extends com.google.protobuf.GeneratedFile { - private A2A() {} - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "A2A"); - } - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); - } - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SendMessageConfiguration_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_Task_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_Task_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_TaskStatus_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_TaskStatus_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_Part_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_Part_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_Message_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_Message_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_Artifact_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_Artifact_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_PushNotificationConfig_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AuthenticationInfo_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentInterface_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentInterface_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentCard_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentCard_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentProvider_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentProvider_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentCapabilities_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentExtension_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentExtension_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentSkill_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentSkill_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AgentCardSignature_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_StringList_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_StringList_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SecurityRequirement_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SecurityScheme_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SecurityScheme_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_APIKeySecurityScheme_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_OAuthFlows_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_OAuthFlows_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_PasswordOAuthFlow_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SendMessageRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_GetTaskRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ListTasksRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ListTasksResponse_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_CancelTaskRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_SendMessageResponse_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_StreamResponse_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_StreamResponse_fieldAccessorTable; - static final com.google.protobuf.Descriptors.Descriptor - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; - static final - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\ta2a.proto\022\006a2a.v1\032\034google/api/annotati" + - "ons.proto\032\027google/api/client.proto\032\037goog" + - "le/api/field_behavior.proto\032\033google/prot" + - "obuf/empty.proto\032\034google/protobuf/struct" + - ".proto\032\037google/protobuf/timestamp.proto\"" + - "\275\001\n\030SendMessageConfiguration\022\035\n\025accepted" + - "_output_modes\030\001 \003(\t\022@\n\030push_notification" + - "_config\030\002 \001(\0132\036.a2a.v1.PushNotificationC" + - "onfig\022\033\n\016history_length\030\003 \001(\005H\000\210\001\001\022\020\n\010bl" + - "ocking\030\004 \001(\010B\021\n\017_history_length\"\313\001\n\004Task" + - "\022\017\n\002id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340" + - "A\002\022\'\n\006status\030\003 \001(\0132\022.a2a.v1.TaskStatusB\003" + - "\340A\002\022#\n\tartifacts\030\004 \003(\0132\020.a2a.v1.Artifact" + - "\022 \n\007history\030\005 \003(\0132\017.a2a.v1.Message\022)\n\010me" + - "tadata\030\006 \001(\0132\027.google.protobuf.Struct\"\204\001" + - "\n\nTaskStatus\022%\n\005state\030\001 \001(\0162\021.a2a.v1.Tas" + - "kStateB\003\340A\002\022 \n\007message\030\002 \001(\0132\017.a2a.v1.Me" + - "ssage\022-\n\ttimestamp\030\003 \001(\0132\032.google.protob" + - "uf.Timestamp\"\270\001\n\004Part\022\016\n\004text\030\001 \001(\tH\000\022\r\n" + - "\003raw\030\002 \001(\014H\000\022\r\n\003url\030\003 \001(\tH\000\022&\n\004data\030\004 \001(" + - "\0132\026.google.protobuf.ValueH\000\022)\n\010metadata\030" + - "\005 \001(\0132\027.google.protobuf.Struct\022\020\n\010filena" + - "me\030\006 \001(\t\022\022\n\nmedia_type\030\007 \001(\tB\t\n\007content\"" + - "\345\001\n\007Message\022\027\n\nmessage_id\030\001 \001(\tB\003\340A\002\022\022\n\n" + - "context_id\030\002 \001(\t\022\017\n\007task_id\030\003 \001(\t\022\037\n\004rol" + - "e\030\004 \001(\0162\014.a2a.v1.RoleB\003\340A\002\022 \n\005parts\030\005 \003(" + - "\0132\014.a2a.v1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027" + - ".google.protobuf.Struct\022\022\n\nextensions\030\007 " + - "\003(\t\022\032\n\022reference_task_ids\030\010 \003(\t\"\250\001\n\010Arti" + - "fact\022\030\n\013artifact_id\030\001 \001(\tB\003\340A\002\022\014\n\004name\030\003" + - " \001(\t\022\023\n\013description\030\004 \001(\t\022 \n\005parts\030\005 \003(\013" + - "2\014.a2a.v1.PartB\003\340A\002\022)\n\010metadata\030\006 \001(\0132\027." + - "google.protobuf.Struct\022\022\n\nextensions\030\007 \003" + - "(\t\"\240\001\n\025TaskStatusUpdateEvent\022\024\n\007task_id\030" + - "\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002\022\'\n\006s" + - "tatus\030\003 \001(\0132\022.a2a.v1.TaskStatusB\003\340A\002\022)\n\010" + - "metadata\030\005 \001(\0132\027.google.protobuf.StructJ" + - "\004\010\004\020\005\"\300\001\n\027TaskArtifactUpdateEvent\022\024\n\007tas" + - "k_id\030\001 \001(\tB\003\340A\002\022\027\n\ncontext_id\030\002 \001(\tB\003\340A\002" + - "\022\'\n\010artifact\030\003 \001(\0132\020.a2a.v1.ArtifactB\003\340A" + - "\002\022\016\n\006append\030\004 \001(\010\022\022\n\nlast_chunk\030\005 \001(\010\022)\n" + - "\010metadata\030\006 \001(\0132\027.google.protobuf.Struct" + - "\"y\n\026PushNotificationConfig\022\n\n\002id\030\001 \001(\t\022\020" + - "\n\003url\030\002 \001(\tB\003\340A\002\022\r\n\005token\030\003 \001(\t\0222\n\016authe" + - "ntication\030\004 \001(\0132\032.a2a.v1.AuthenticationI" + - "nfo\">\n\022AuthenticationInfo\022\023\n\006scheme\030\001 \001(" + - "\tB\003\340A\002\022\023\n\013credentials\030\002 \001(\t\"p\n\016AgentInte" + - "rface\022\020\n\003url\030\001 \001(\tB\003\340A\002\022\035\n\020protocol_bind" + - "ing\030\002 \001(\tB\003\340A\002\022\016\n\006tenant\030\003 \001(\t\022\035\n\020protoc" + - "ol_version\030\004 \001(\tB\003\340A\002\"\314\005\n\tAgentCard\022\021\n\004n" + - "ame\030\001 \001(\tB\003\340A\002\022\030\n\013description\030\002 \001(\tB\003\340A\002" + - "\0229\n\024supported_interfaces\030\023 \003(\0132\026.a2a.v1." + - "AgentInterfaceB\003\340A\002\022\'\n\010provider\030\004 \001(\0132\025." + - "a2a.v1.AgentProvider\022\024\n\007version\030\005 \001(\tB\003\340" + - "A\002\022\036\n\021documentation_url\030\006 \001(\tH\000\210\001\001\0224\n\014ca" + - "pabilities\030\007 \001(\0132\031.a2a.v1.AgentCapabilit" + - "iesB\003\340A\002\022@\n\020security_schemes\030\010 \003(\0132&.a2a" + - ".v1.AgentCard.SecuritySchemesEntry\022:\n\025se" + - "curity_requirements\030\r \003(\0132\033.a2a.v1.Secur" + - "ityRequirement\022 \n\023default_input_modes\030\n " + - "\003(\tB\003\340A\002\022!\n\024default_output_modes\030\013 \003(\tB\003" + - "\340A\002\022\'\n\006skills\030\014 \003(\0132\022.a2a.v1.AgentSkillB" + - "\003\340A\002\022.\n\nsignatures\030\021 \003(\0132\032.a2a.v1.AgentC" + - "ardSignature\022\025\n\010icon_url\030\022 \001(\tH\001\210\001\001\032N\n\024S" + - "ecuritySchemesEntry\022\013\n\003key\030\001 \001(\t\022%\n\005valu" + - "e\030\002 \001(\0132\026.a2a.v1.SecurityScheme:\0028\001B\024\n\022_" + - "documentation_urlB\013\n\t_icon_urlJ\004\010\003\020\004J\004\010\t" + - "\020\nJ\004\010\016\020\017J\004\010\017\020\020J\004\010\020\020\021\"<\n\rAgentProvider\022\020\n" + - "\003url\030\001 \001(\tB\003\340A\002\022\031\n\014organization\030\002 \001(\tB\003\340" + - "A\002\"\335\001\n\021AgentCapabilities\022\026\n\tstreaming\030\001 " + - "\001(\010H\000\210\001\001\022\037\n\022push_notifications\030\002 \001(\010H\001\210\001" + - "\001\022*\n\nextensions\030\003 \003(\0132\026.a2a.v1.AgentExte" + - "nsion\022 \n\023extended_agent_card\030\005 \001(\010H\002\210\001\001B" + - "\014\n\n_streamingB\025\n\023_push_notificationsB\026\n\024" + - "_extended_agent_cardJ\004\010\004\020\005\"m\n\016AgentExten" + - "sion\022\013\n\003uri\030\001 \001(\t\022\023\n\013description\030\002 \001(\t\022\020" + - "\n\010required\030\003 \001(\010\022\'\n\006params\030\004 \001(\0132\027.googl" + - "e.protobuf.Struct\"\326\001\n\nAgentSkill\022\017\n\002id\030\001" + - " \001(\tB\003\340A\002\022\021\n\004name\030\002 \001(\tB\003\340A\002\022\030\n\013descript" + - "ion\030\003 \001(\tB\003\340A\002\022\021\n\004tags\030\004 \003(\tB\003\340A\002\022\020\n\010exa" + - "mples\030\005 \003(\t\022\023\n\013input_modes\030\006 \003(\t\022\024\n\014outp" + - "ut_modes\030\007 \003(\t\022:\n\025security_requirements\030" + - "\010 \003(\0132\033.a2a.v1.SecurityRequirement\"m\n\022Ag" + - "entCardSignature\022\026\n\tprotected\030\001 \001(\tB\003\340A\002" + - "\022\026\n\tsignature\030\002 \001(\tB\003\340A\002\022\'\n\006header\030\003 \001(\013" + - "2\027.google.protobuf.Struct\"\232\001\n\032TaskPushNo" + - "tificationConfig\022\016\n\006tenant\030\004 \001(\t\022\017\n\002id\030\001" + - " \001(\tB\003\340A\002\022\024\n\007task_id\030\003 \001(\tB\003\340A\002\022E\n\030push_" + - "notification_config\030\002 \001(\0132\036.a2a.v1.PushN" + - "otificationConfigB\003\340A\002\"\032\n\nStringList\022\014\n\004" + - "list\030\001 \003(\t\"\224\001\n\023SecurityRequirement\0229\n\007sc" + - "hemes\030\001 \003(\0132(.a2a.v1.SecurityRequirement" + - ".SchemesEntry\032B\n\014SchemesEntry\022\013\n\003key\030\001 \001" + - "(\t\022!\n\005value\030\002 \001(\0132\022.a2a.v1.StringList:\0028" + - "\001\"\361\002\n\016SecurityScheme\022?\n\027api_key_security" + - "_scheme\030\001 \001(\0132\034.a2a.v1.APIKeySecuritySch" + - "emeH\000\022C\n\031http_auth_security_scheme\030\002 \001(\013" + - "2\036.a2a.v1.HTTPAuthSecuritySchemeH\000\022>\n\026oa" + - "uth2_security_scheme\030\003 \001(\0132\034.a2a.v1.OAut" + - "h2SecuritySchemeH\000\022N\n\037open_id_connect_se" + - "curity_scheme\030\004 \001(\0132#.a2a.v1.OpenIdConne" + - "ctSecuritySchemeH\000\022?\n\024mtls_security_sche" + - "me\030\005 \001(\0132\037.a2a.v1.MutualTlsSecuritySchem" + - "eH\000B\010\n\006scheme\"U\n\024APIKeySecurityScheme\022\023\n" + - "\013description\030\001 \001(\t\022\025\n\010location\030\002 \001(\tB\003\340A" + - "\002\022\021\n\004name\030\003 \001(\tB\003\340A\002\"Y\n\026HTTPAuthSecurity" + - "Scheme\022\023\n\013description\030\001 \001(\t\022\023\n\006scheme\030\002 " + - "\001(\tB\003\340A\002\022\025\n\rbearer_format\030\003 \001(\t\"p\n\024OAuth" + - "2SecurityScheme\022\023\n\013description\030\001 \001(\t\022&\n\005" + - "flows\030\002 \001(\0132\022.a2a.v1.OAuthFlowsB\003\340A\002\022\033\n\023" + - "oauth2_metadata_url\030\003 \001(\t\"T\n\033OpenIdConne" + - "ctSecurityScheme\022\023\n\013description\030\001 \001(\t\022 \n" + - "\023open_id_connect_url\030\002 \001(\tB\003\340A\002\".\n\027Mutua" + - "lTlsSecurityScheme\022\023\n\013description\030\001 \001(\t\"" + - "\262\002\n\nOAuthFlows\022@\n\022authorization_code\030\001 \001" + - "(\0132\".a2a.v1.AuthorizationCodeOAuthFlowH\000" + - "\022@\n\022client_credentials\030\002 \001(\0132\".a2a.v1.Cl" + - "ientCredentialsOAuthFlowH\000\0221\n\010implicit\030\003" + - " \001(\0132\031.a2a.v1.ImplicitOAuthFlowB\002\030\001H\000\0221\n" + - "\010password\030\004 \001(\0132\031.a2a.v1.PasswordOAuthFl" + - "owB\002\030\001H\000\0222\n\013device_code\030\005 \001(\0132\033.a2a.v1.D" + - "eviceCodeOAuthFlowH\000B\006\n\004flow\"\364\001\n\032Authori" + - "zationCodeOAuthFlow\022\036\n\021authorization_url" + - "\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030\002 \001(\tB\003\340A\002\022\023\n\013r" + - "efresh_url\030\003 \001(\t\022C\n\006scopes\030\004 \003(\0132..a2a.v" + - "1.AuthorizationCodeOAuthFlow.ScopesEntry" + - "B\003\340A\002\022\025\n\rpkce_required\030\005 \001(\010\032-\n\013ScopesEn" + - "try\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\275\001\n\032" + - "ClientCredentialsOAuthFlow\022\026\n\ttoken_url\030" + - "\001 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\002 \001(\t\022C\n\006scope" + - "s\030\003 \003(\0132..a2a.v1.ClientCredentialsOAuthF" + - "low.ScopesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003k" + - "ey\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\251\001\n\021Implicit" + - "OAuthFlow\022\031\n\021authorization_url\030\001 \001(\t\022\023\n\013" + - "refresh_url\030\002 \001(\t\0225\n\006scopes\030\003 \003(\0132%.a2a." + - "v1.ImplicitOAuthFlow.ScopesEntry\032-\n\013Scop" + - "esEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001\"" + - "\241\001\n\021PasswordOAuthFlow\022\021\n\ttoken_url\030\001 \001(\t" + - "\022\023\n\013refresh_url\030\002 \001(\t\0225\n\006scopes\030\003 \003(\0132%." + - "a2a.v1.PasswordOAuthFlow.ScopesEntry\032-\n\013" + - "ScopesEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:" + - "\0028\001\"\326\001\n\023DeviceCodeOAuthFlow\022%\n\030device_au" + - "thorization_url\030\001 \001(\tB\003\340A\002\022\026\n\ttoken_url\030" + - "\002 \001(\tB\003\340A\002\022\023\n\013refresh_url\030\003 \001(\t\022<\n\006scope" + - "s\030\004 \003(\0132\'.a2a.v1.DeviceCodeOAuthFlow.Sco" + - "pesEntryB\003\340A\002\032-\n\013ScopesEntry\022\013\n\003key\030\001 \001(" + - "\t\022\r\n\005value\030\002 \001(\t:\0028\001\"\257\001\n\022SendMessageRequ" + - "est\022\016\n\006tenant\030\004 \001(\t\022%\n\007message\030\001 \001(\0132\017.a" + - "2a.v1.MessageB\003\340A\002\0227\n\rconfiguration\030\002 \001(" + - "\0132 .a2a.v1.SendMessageConfiguration\022)\n\010m" + - "etadata\030\003 \001(\0132\027.google.protobuf.Struct\"a" + - "\n\016GetTaskRequest\022\016\n\006tenant\030\003 \001(\t\022\017\n\002id\030\001" + - " \001(\tB\003\340A\002\022\033\n\016history_length\030\002 \001(\005H\000\210\001\001B\021" + - "\n\017_history_length\"\265\002\n\020ListTasksRequest\022\016" + - "\n\006tenant\030\t \001(\t\022\022\n\ncontext_id\030\001 \001(\t\022!\n\006st" + - "atus\030\002 \001(\0162\021.a2a.v1.TaskState\022\026\n\tpage_si" + - "ze\030\003 \001(\005H\000\210\001\001\022\022\n\npage_token\030\004 \001(\t\022\033\n\016his" + - "tory_length\030\005 \001(\005H\001\210\001\001\022:\n\026status_timesta" + - "mp_after\030\006 \001(\0132\032.google.protobuf.Timesta" + - "mp\022\036\n\021include_artifacts\030\007 \001(\010H\002\210\001\001B\014\n\n_p" + - "age_sizeB\021\n\017_history_lengthB\024\n\022_include_" + - "artifacts\"\204\001\n\021ListTasksResponse\022 \n\005tasks" + - "\030\001 \003(\0132\014.a2a.v1.TaskB\003\340A\002\022\034\n\017next_page_t" + - "oken\030\002 \001(\tB\003\340A\002\022\026\n\tpage_size\030\003 \001(\005B\003\340A\002\022" + - "\027\n\ntotal_size\030\004 \001(\005B\003\340A\002\"4\n\021CancelTaskRe" + - "quest\022\016\n\006tenant\030\002 \001(\t\022\017\n\002id\030\001 \001(\tB\003\340A\002\"]" + - "\n$GetTaskPushNotificationConfigRequest\022\016" + - "\n\006tenant\030\002 \001(\t\022\024\n\007task_id\030\003 \001(\tB\003\340A\002\022\017\n\002" + - "id\030\001 \001(\tB\003\340A\002\"`\n\'DeleteTaskPushNotificat" + - "ionConfigRequest\022\016\n\006tenant\030\002 \001(\t\022\024\n\007task" + - "_id\030\003 \001(\tB\003\340A\002\022\017\n\002id\030\001 \001(\tB\003\340A\002\"\242\001\n\'Crea" + - "teTaskPushNotificationConfigRequest\022\016\n\006t" + - "enant\030\004 \001(\t\022\024\n\007task_id\030\001 \001(\tB\003\340A\002\022\026\n\tcon" + - "fig_id\030\002 \001(\tB\003\340A\002\0223\n\006config\030\005 \001(\0132\036.a2a." + - "v1.PushNotificationConfigB\003\340A\002J\004\010\003\020\004\"9\n\026" + - "SubscribeToTaskRequest\022\016\n\006tenant\030\002 \001(\t\022\017" + - "\n\002id\030\001 \001(\tB\003\340A\002\"t\n%ListTaskPushNotificat" + - "ionConfigRequest\022\016\n\006tenant\030\004 \001(\t\022\024\n\007task" + - "_id\030\001 \001(\tB\003\340A\002\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npag" + - "e_token\030\003 \001(\t\"-\n\033GetExtendedAgentCardReq" + - "uest\022\016\n\006tenant\030\001 \001(\t\"b\n\023SendMessageRespo" + - "nse\022\034\n\004task\030\001 \001(\0132\014.a2a.v1.TaskH\000\022\"\n\007mes" + - "sage\030\002 \001(\0132\017.a2a.v1.MessageH\000B\t\n\007payload" + - "\"\321\001\n\016StreamResponse\022\034\n\004task\030\001 \001(\0132\014.a2a." + - "v1.TaskH\000\022\"\n\007message\030\002 \001(\0132\017.a2a.v1.Mess" + - "ageH\000\0226\n\rstatus_update\030\003 \001(\0132\035.a2a.v1.Ta" + - "skStatusUpdateEventH\000\022:\n\017artifact_update" + - "\030\004 \001(\0132\037.a2a.v1.TaskArtifactUpdateEventH" + - "\000B\t\n\007payload\"v\n&ListTaskPushNotification" + - "ConfigResponse\0223\n\007configs\030\001 \003(\0132\".a2a.v1" + - ".TaskPushNotificationConfig\022\027\n\017next_page" + - "_token\030\002 \001(\t*\371\001\n\tTaskState\022\032\n\026TASK_STATE" + - "_UNSPECIFIED\020\000\022\030\n\024TASK_STATE_SUBMITTED\020\001" + - "\022\026\n\022TASK_STATE_WORKING\020\002\022\030\n\024TASK_STATE_C" + - "OMPLETED\020\003\022\025\n\021TASK_STATE_FAILED\020\004\022\027\n\023TAS" + - "K_STATE_CANCELED\020\005\022\035\n\031TASK_STATE_INPUT_R" + - "EQUIRED\020\006\022\027\n\023TASK_STATE_REJECTED\020\007\022\034\n\030TA" + - "SK_STATE_AUTH_REQUIRED\020\010*;\n\004Role\022\024\n\020ROLE" + - "_UNSPECIFIED\020\000\022\r\n\tROLE_USER\020\001\022\016\n\nROLE_AG" + - "ENT\020\0022\352\016\n\nA2AService\022}\n\013SendMessage\022\032.a2" + - "a.v1.SendMessageRequest\032\033.a2a.v1.SendMes" + - "sageResponse\"5\202\323\344\223\002/\"\r/message:send:\001*Z\033" + - "\"\026/{tenant}/message:send:\001*\022\207\001\n\024SendStre" + - "amingMessage\022\032.a2a.v1.SendMessageRequest" + - "\032\026.a2a.v1.StreamResponse\"9\202\323\344\223\0023\"\017/messa" + - "ge:stream:\001*Z\035\"\030/{tenant}/message:stream" + - ":\001*0\001\022e\n\007GetTask\022\026.a2a.v1.GetTaskRequest" + - "\032\014.a2a.v1.Task\"4\332A\002id\202\323\344\223\002)\022\r/tasks/{id=" + - "*}Z\030\022\026/{tenant}/tasks/{id=*}\022c\n\tListTask" + - "s\022\030.a2a.v1.ListTasksRequest\032\031.a2a.v1.Lis" + - "tTasksResponse\"!\202\323\344\223\002\033\022\006/tasksZ\021\022\017/{tena" + - "nt}/tasks\022z\n\nCancelTask\022\031.a2a.v1.CancelT" + - "askRequest\032\014.a2a.v1.Task\"C\202\323\344\223\002=\"\024/tasks" + - "/{id=*}:cancel:\001*Z\"\"\035/{tenant}/tasks/{id" + - "=*}:cancel:\001*\022\220\001\n\017SubscribeToTask\022\036.a2a." + - "v1.SubscribeToTaskRequest\032\026.a2a.v1.Strea" + - "mResponse\"C\202\323\344\223\002=\022\027/tasks/{id=*}:subscri" + - "beZ\"\022 /{tenant}/tasks/{id=*}:subscribe0\001" + - "\022\204\002\n CreateTaskPushNotificationConfig\022/." + - "a2a.v1.CreateTaskPushNotificationConfigR" + - "equest\032\".a2a.v1.TaskPushNotificationConf" + - "ig\"\212\001\332A\016task_id,config\202\323\344\223\002s\"*/tasks/{ta" + - "sk_id=*}/pushNotificationConfigs:\006config" + - "Z=\"3/{tenant}/tasks/{task_id=*}/pushNoti" + - "ficationConfigs:\006config\022\370\001\n\035GetTaskPushN" + - "otificationConfig\022,.a2a.v1.GetTaskPushNo" + - "tificationConfigRequest\032\".a2a.v1.TaskPus" + - "hNotificationConfig\"\204\001\332A\ntask_id,id\202\323\344\223\002" + - "q\0221/tasks/{task_id=*}/pushNotificationCo" + - "nfigs/{id=*}Z<\022:/{tenant}/tasks/{task_id" + - "=*}/pushNotificationConfigs/{id=*}\022\364\001\n\036L" + - "istTaskPushNotificationConfig\022-.a2a.v1.L" + - "istTaskPushNotificationConfigRequest\032..a" + - "2a.v1.ListTaskPushNotificationConfigResp" + - "onse\"s\332A\007task_id\202\323\344\223\002c\022*/tasks/{task_id=" + - "*}/pushNotificationConfigsZ5\0223/{tenant}/" + - "tasks/{task_id=*}/pushNotificationConfig" + - "s\022\211\001\n\024GetExtendedAgentCard\022#.a2a.v1.GetE" + - "xtendedAgentCardRequest\032\021.a2a.v1.AgentCa" + - "rd\"9\202\323\344\223\0023\022\022/extendedAgentCardZ\035\022\033/{tena" + - "nt}/extendedAgentCard\022\362\001\n DeleteTaskPush" + - "NotificationConfig\022/.a2a.v1.DeleteTaskPu" + - "shNotificationConfigRequest\032\026.google.pro" + - "tobuf.Empty\"\204\001\332A\ntask_id,id\202\323\344\223\002q*1/task" + - "s/{task_id=*}/pushNotificationConfigs/{i" + - "d=*}Z<*:/{tenant}/tasks/{task_id=*}/push" + - "NotificationConfigs/{id=*}B7\n\013io.a2a.grp" + - "cB\003A2AP\001Z\030google.golang.org/a2a/v1\252\002\006A2a" + - ".V1b\006proto3" - }; - descriptor = com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - com.google.api.AnnotationsProto.getDescriptor(), - com.google.api.ClientProto.getDescriptor(), - com.google.api.FieldBehaviorProto.getDescriptor(), - com.google.protobuf.EmptyProto.getDescriptor(), - com.google.protobuf.StructProto.getDescriptor(), - com.google.protobuf.TimestampProto.getDescriptor(), - }); - internal_static_a2a_v1_SendMessageConfiguration_descriptor = - getDescriptor().getMessageType(0); - internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SendMessageConfiguration_descriptor, - new java.lang.String[] { "AcceptedOutputModes", "PushNotificationConfig", "HistoryLength", "Blocking", }); - internal_static_a2a_v1_Task_descriptor = - getDescriptor().getMessageType(1); - internal_static_a2a_v1_Task_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Task_descriptor, - new java.lang.String[] { "Id", "ContextId", "Status", "Artifacts", "History", "Metadata", }); - internal_static_a2a_v1_TaskStatus_descriptor = - getDescriptor().getMessageType(2); - internal_static_a2a_v1_TaskStatus_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskStatus_descriptor, - new java.lang.String[] { "State", "Message", "Timestamp", }); - internal_static_a2a_v1_Part_descriptor = - getDescriptor().getMessageType(3); - internal_static_a2a_v1_Part_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Part_descriptor, - new java.lang.String[] { "Text", "Raw", "Url", "Data", "Metadata", "Filename", "MediaType", "Content", }); - internal_static_a2a_v1_Message_descriptor = - getDescriptor().getMessageType(4); - internal_static_a2a_v1_Message_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Message_descriptor, - new java.lang.String[] { "MessageId", "ContextId", "TaskId", "Role", "Parts", "Metadata", "Extensions", "ReferenceTaskIds", }); - internal_static_a2a_v1_Artifact_descriptor = - getDescriptor().getMessageType(5); - internal_static_a2a_v1_Artifact_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_Artifact_descriptor, - new java.lang.String[] { "ArtifactId", "Name", "Description", "Parts", "Metadata", "Extensions", }); - internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor = - getDescriptor().getMessageType(6); - internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor, - new java.lang.String[] { "TaskId", "ContextId", "Status", "Metadata", }); - internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor = - getDescriptor().getMessageType(7); - internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor, - new java.lang.String[] { "TaskId", "ContextId", "Artifact", "Append", "LastChunk", "Metadata", }); - internal_static_a2a_v1_PushNotificationConfig_descriptor = - getDescriptor().getMessageType(8); - internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PushNotificationConfig_descriptor, - new java.lang.String[] { "Id", "Url", "Token", "Authentication", }); - internal_static_a2a_v1_AuthenticationInfo_descriptor = - getDescriptor().getMessageType(9); - internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AuthenticationInfo_descriptor, - new java.lang.String[] { "Scheme", "Credentials", }); - internal_static_a2a_v1_AgentInterface_descriptor = - getDescriptor().getMessageType(10); - internal_static_a2a_v1_AgentInterface_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentInterface_descriptor, - new java.lang.String[] { "Url", "ProtocolBinding", "Tenant", "ProtocolVersion", }); - internal_static_a2a_v1_AgentCard_descriptor = - getDescriptor().getMessageType(11); - internal_static_a2a_v1_AgentCard_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCard_descriptor, - new java.lang.String[] { "Name", "Description", "SupportedInterfaces", "Provider", "Version", "DocumentationUrl", "Capabilities", "SecuritySchemes", "SecurityRequirements", "DefaultInputModes", "DefaultOutputModes", "Skills", "Signatures", "IconUrl", }); - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor = - internal_static_a2a_v1_AgentCard_descriptor.getNestedType(0); - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_AgentProvider_descriptor = - getDescriptor().getMessageType(12); - internal_static_a2a_v1_AgentProvider_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentProvider_descriptor, - new java.lang.String[] { "Url", "Organization", }); - internal_static_a2a_v1_AgentCapabilities_descriptor = - getDescriptor().getMessageType(13); - internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCapabilities_descriptor, - new java.lang.String[] { "Streaming", "PushNotifications", "Extensions", "ExtendedAgentCard", }); - internal_static_a2a_v1_AgentExtension_descriptor = - getDescriptor().getMessageType(14); - internal_static_a2a_v1_AgentExtension_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentExtension_descriptor, - new java.lang.String[] { "Uri", "Description", "Required", "Params", }); - internal_static_a2a_v1_AgentSkill_descriptor = - getDescriptor().getMessageType(15); - internal_static_a2a_v1_AgentSkill_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentSkill_descriptor, - new java.lang.String[] { "Id", "Name", "Description", "Tags", "Examples", "InputModes", "OutputModes", "SecurityRequirements", }); - internal_static_a2a_v1_AgentCardSignature_descriptor = - getDescriptor().getMessageType(16); - internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AgentCardSignature_descriptor, - new java.lang.String[] { "Protected", "Signature", "Header", }); - internal_static_a2a_v1_TaskPushNotificationConfig_descriptor = - getDescriptor().getMessageType(17); - internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_TaskPushNotificationConfig_descriptor, - new java.lang.String[] { "Tenant", "Id", "TaskId", "PushNotificationConfig", }); - internal_static_a2a_v1_StringList_descriptor = - getDescriptor().getMessageType(18); - internal_static_a2a_v1_StringList_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_StringList_descriptor, - new java.lang.String[] { "List", }); - internal_static_a2a_v1_SecurityRequirement_descriptor = - getDescriptor().getMessageType(19); - internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SecurityRequirement_descriptor, - new java.lang.String[] { "Schemes", }); - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor = - internal_static_a2a_v1_SecurityRequirement_descriptor.getNestedType(0); - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_SecurityScheme_descriptor = - getDescriptor().getMessageType(20); - internal_static_a2a_v1_SecurityScheme_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SecurityScheme_descriptor, - new java.lang.String[] { "ApiKeySecurityScheme", "HttpAuthSecurityScheme", "Oauth2SecurityScheme", "OpenIdConnectSecurityScheme", "MtlsSecurityScheme", "Scheme", }); - internal_static_a2a_v1_APIKeySecurityScheme_descriptor = - getDescriptor().getMessageType(21); - internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_APIKeySecurityScheme_descriptor, - new java.lang.String[] { "Description", "Location", "Name", }); - internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor = - getDescriptor().getMessageType(22); - internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor, - new java.lang.String[] { "Description", "Scheme", "BearerFormat", }); - internal_static_a2a_v1_OAuth2SecurityScheme_descriptor = - getDescriptor().getMessageType(23); - internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_OAuth2SecurityScheme_descriptor, - new java.lang.String[] { "Description", "Flows", "Oauth2MetadataUrl", }); - internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor = - getDescriptor().getMessageType(24); - internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor, - new java.lang.String[] { "Description", "OpenIdConnectUrl", }); - internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor = - getDescriptor().getMessageType(25); - internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor, - new java.lang.String[] { "Description", }); - internal_static_a2a_v1_OAuthFlows_descriptor = - getDescriptor().getMessageType(26); - internal_static_a2a_v1_OAuthFlows_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_OAuthFlows_descriptor, - new java.lang.String[] { "AuthorizationCode", "ClientCredentials", "Implicit", "Password", "DeviceCode", "Flow", }); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor = - getDescriptor().getMessageType(27); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor, - new java.lang.String[] { "AuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", "PkceRequired", }); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor = - getDescriptor().getMessageType(28); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor, - new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor = - getDescriptor().getMessageType(29); - internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor, - new java.lang.String[] { "AuthorizationUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_ImplicitOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_PasswordOAuthFlow_descriptor = - getDescriptor().getMessageType(30); - internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PasswordOAuthFlow_descriptor, - new java.lang.String[] { "TokenUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_PasswordOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor = - getDescriptor().getMessageType(31); - internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor, - new java.lang.String[] { "DeviceAuthorizationUrl", "TokenUrl", "RefreshUrl", "Scopes", }); - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor = - internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor.getNestedType(0); - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_a2a_v1_SendMessageRequest_descriptor = - getDescriptor().getMessageType(32); - internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SendMessageRequest_descriptor, - new java.lang.String[] { "Tenant", "Message", "Configuration", "Metadata", }); - internal_static_a2a_v1_GetTaskRequest_descriptor = - getDescriptor().getMessageType(33); - internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_GetTaskRequest_descriptor, - new java.lang.String[] { "Tenant", "Id", "HistoryLength", }); - internal_static_a2a_v1_ListTasksRequest_descriptor = - getDescriptor().getMessageType(34); - internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTasksRequest_descriptor, - new java.lang.String[] { "Tenant", "ContextId", "Status", "PageSize", "PageToken", "HistoryLength", "StatusTimestampAfter", "IncludeArtifacts", }); - internal_static_a2a_v1_ListTasksResponse_descriptor = - getDescriptor().getMessageType(35); - internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTasksResponse_descriptor, - new java.lang.String[] { "Tasks", "NextPageToken", "PageSize", "TotalSize", }); - internal_static_a2a_v1_CancelTaskRequest_descriptor = - getDescriptor().getMessageType(36); - internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_CancelTaskRequest_descriptor, - new java.lang.String[] { "Tenant", "Id", }); - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(37); - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "TaskId", "Id", }); - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(38); - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "TaskId", "Id", }); - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(39); - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "TaskId", "ConfigId", "Config", }); - internal_static_a2a_v1_SubscribeToTaskRequest_descriptor = - getDescriptor().getMessageType(40); - internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SubscribeToTaskRequest_descriptor, - new java.lang.String[] { "Tenant", "Id", }); - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor = - getDescriptor().getMessageType(41); - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor, - new java.lang.String[] { "Tenant", "TaskId", "PageSize", "PageToken", }); - internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor = - getDescriptor().getMessageType(42); - internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor, - new java.lang.String[] { "Tenant", }); - internal_static_a2a_v1_SendMessageResponse_descriptor = - getDescriptor().getMessageType(43); - internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_SendMessageResponse_descriptor, - new java.lang.String[] { "Task", "Message", "Payload", }); - internal_static_a2a_v1_StreamResponse_descriptor = - getDescriptor().getMessageType(44); - internal_static_a2a_v1_StreamResponse_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_StreamResponse_descriptor, - new java.lang.String[] { "Task", "Message", "StatusUpdate", "ArtifactUpdate", "Payload", }); - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor = - getDescriptor().getMessageType(45); - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor, - new java.lang.String[] { "Configs", "NextPageToken", }); - descriptor.resolveAllFeaturesImmutable(); - com.google.api.AnnotationsProto.getDescriptor(); - com.google.api.ClientProto.getDescriptor(); - com.google.api.FieldBehaviorProto.getDescriptor(); - com.google.protobuf.EmptyProto.getDescriptor(); - com.google.protobuf.StructProto.getDescriptor(); - com.google.protobuf.TimestampProto.getDescriptor(); - com.google.protobuf.ExtensionRegistry registry = - com.google.protobuf.ExtensionRegistry.newInstance(); - registry.add(com.google.api.FieldBehaviorProto.fieldBehavior); - registry.add(com.google.api.AnnotationsProto.http); - registry.add(com.google.api.ClientProto.methodSignature); - com.google.protobuf.Descriptors.FileDescriptor - .internalUpdateFileDescriptor(descriptor, registry); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java b/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java deleted file mode 100644 index 6d179b674..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/A2AServiceGrpc.java +++ /dev/null @@ -1,1313 +0,0 @@ -package io.a2a.grpc; - -import static io.grpc.MethodDescriptor.generateFullMethodName; - -/** - *
- * A2AService defines the operations of the A2A protocol.
- * 
- */ -@io.grpc.stub.annotations.GrpcGenerated -public final class A2AServiceGrpc { - - private A2AServiceGrpc() {} - - public static final java.lang.String SERVICE_NAME = "a2a.v1.A2AService"; - - // Static method descriptors that strictly reflect the proto. - private static volatile io.grpc.MethodDescriptor getSendMessageMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "SendMessage", - requestType = io.a2a.grpc.SendMessageRequest.class, - responseType = io.a2a.grpc.SendMessageResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getSendMessageMethod() { - io.grpc.MethodDescriptor getSendMessageMethod; - if ((getSendMessageMethod = A2AServiceGrpc.getSendMessageMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getSendMessageMethod = A2AServiceGrpc.getSendMessageMethod) == null) { - A2AServiceGrpc.getSendMessageMethod = getSendMessageMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SendMessage")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SendMessageRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SendMessageResponse.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SendMessage")) - .build(); - } - } - } - return getSendMessageMethod; - } - - private static volatile io.grpc.MethodDescriptor getSendStreamingMessageMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "SendStreamingMessage", - requestType = io.a2a.grpc.SendMessageRequest.class, - responseType = io.a2a.grpc.StreamResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) - public static io.grpc.MethodDescriptor getSendStreamingMessageMethod() { - io.grpc.MethodDescriptor getSendStreamingMessageMethod; - if ((getSendStreamingMessageMethod = A2AServiceGrpc.getSendStreamingMessageMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getSendStreamingMessageMethod = A2AServiceGrpc.getSendStreamingMessageMethod) == null) { - A2AServiceGrpc.getSendStreamingMessageMethod = getSendStreamingMessageMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SendStreamingMessage")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SendMessageRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.StreamResponse.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SendStreamingMessage")) - .build(); - } - } - } - return getSendStreamingMessageMethod; - } - - private static volatile io.grpc.MethodDescriptor getGetTaskMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "GetTask", - requestType = io.a2a.grpc.GetTaskRequest.class, - responseType = io.a2a.grpc.Task.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getGetTaskMethod() { - io.grpc.MethodDescriptor getGetTaskMethod; - if ((getGetTaskMethod = A2AServiceGrpc.getGetTaskMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getGetTaskMethod = A2AServiceGrpc.getGetTaskMethod) == null) { - A2AServiceGrpc.getGetTaskMethod = getGetTaskMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetTask")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.GetTaskRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.Task.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetTask")) - .build(); - } - } - } - return getGetTaskMethod; - } - - private static volatile io.grpc.MethodDescriptor getListTasksMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "ListTasks", - requestType = io.a2a.grpc.ListTasksRequest.class, - responseType = io.a2a.grpc.ListTasksResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getListTasksMethod() { - io.grpc.MethodDescriptor getListTasksMethod; - if ((getListTasksMethod = A2AServiceGrpc.getListTasksMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getListTasksMethod = A2AServiceGrpc.getListTasksMethod) == null) { - A2AServiceGrpc.getListTasksMethod = getListTasksMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListTasks")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTasksRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTasksResponse.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("ListTasks")) - .build(); - } - } - } - return getListTasksMethod; - } - - private static volatile io.grpc.MethodDescriptor getCancelTaskMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "CancelTask", - requestType = io.a2a.grpc.CancelTaskRequest.class, - responseType = io.a2a.grpc.Task.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getCancelTaskMethod() { - io.grpc.MethodDescriptor getCancelTaskMethod; - if ((getCancelTaskMethod = A2AServiceGrpc.getCancelTaskMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getCancelTaskMethod = A2AServiceGrpc.getCancelTaskMethod) == null) { - A2AServiceGrpc.getCancelTaskMethod = getCancelTaskMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CancelTask")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.CancelTaskRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.Task.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CancelTask")) - .build(); - } - } - } - return getCancelTaskMethod; - } - - private static volatile io.grpc.MethodDescriptor getSubscribeToTaskMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "SubscribeToTask", - requestType = io.a2a.grpc.SubscribeToTaskRequest.class, - responseType = io.a2a.grpc.StreamResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) - public static io.grpc.MethodDescriptor getSubscribeToTaskMethod() { - io.grpc.MethodDescriptor getSubscribeToTaskMethod; - if ((getSubscribeToTaskMethod = A2AServiceGrpc.getSubscribeToTaskMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getSubscribeToTaskMethod = A2AServiceGrpc.getSubscribeToTaskMethod) == null) { - A2AServiceGrpc.getSubscribeToTaskMethod = getSubscribeToTaskMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "SubscribeToTask")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.SubscribeToTaskRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.StreamResponse.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("SubscribeToTask")) - .build(); - } - } - } - return getSubscribeToTaskMethod; - } - - private static volatile io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "CreateTaskPushNotificationConfig", - requestType = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, - responseType = io.a2a.grpc.TaskPushNotificationConfig.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getCreateTaskPushNotificationConfigMethod; - if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getCreateTaskPushNotificationConfigMethod = A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod) == null) { - A2AServiceGrpc.getCreateTaskPushNotificationConfigMethod = getCreateTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "CreateTaskPushNotificationConfig")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("CreateTaskPushNotificationConfig")) - .build(); - } - } - } - return getCreateTaskPushNotificationConfigMethod; - } - - private static volatile io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "GetTaskPushNotificationConfig", - requestType = io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, - responseType = io.a2a.grpc.TaskPushNotificationConfig.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getGetTaskPushNotificationConfigMethod; - if ((getGetTaskPushNotificationConfigMethod = A2AServiceGrpc.getGetTaskPushNotificationConfigMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getGetTaskPushNotificationConfigMethod = A2AServiceGrpc.getGetTaskPushNotificationConfigMethod) == null) { - A2AServiceGrpc.getGetTaskPushNotificationConfigMethod = getGetTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetTaskPushNotificationConfig")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetTaskPushNotificationConfig")) - .build(); - } - } - } - return getGetTaskPushNotificationConfigMethod; - } - - private static volatile io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "ListTaskPushNotificationConfig", - requestType = io.a2a.grpc.ListTaskPushNotificationConfigRequest.class, - responseType = io.a2a.grpc.ListTaskPushNotificationConfigResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getListTaskPushNotificationConfigMethod; - if ((getListTaskPushNotificationConfigMethod = A2AServiceGrpc.getListTaskPushNotificationConfigMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getListTaskPushNotificationConfigMethod = A2AServiceGrpc.getListTaskPushNotificationConfigMethod) == null) { - A2AServiceGrpc.getListTaskPushNotificationConfigMethod = getListTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "ListTaskPushNotificationConfig")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("ListTaskPushNotificationConfig")) - .build(); - } - } - } - return getListTaskPushNotificationConfigMethod; - } - - private static volatile io.grpc.MethodDescriptor getGetExtendedAgentCardMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "GetExtendedAgentCard", - requestType = io.a2a.grpc.GetExtendedAgentCardRequest.class, - responseType = io.a2a.grpc.AgentCard.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getGetExtendedAgentCardMethod() { - io.grpc.MethodDescriptor getGetExtendedAgentCardMethod; - if ((getGetExtendedAgentCardMethod = A2AServiceGrpc.getGetExtendedAgentCardMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getGetExtendedAgentCardMethod = A2AServiceGrpc.getGetExtendedAgentCardMethod) == null) { - A2AServiceGrpc.getGetExtendedAgentCardMethod = getGetExtendedAgentCardMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "GetExtendedAgentCard")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.GetExtendedAgentCardRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.AgentCard.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("GetExtendedAgentCard")) - .build(); - } - } - } - return getGetExtendedAgentCardMethod; - } - - private static volatile io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "DeleteTaskPushNotificationConfig", - requestType = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, - responseType = com.google.protobuf.Empty.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod() { - io.grpc.MethodDescriptor getDeleteTaskPushNotificationConfigMethod; - if ((getDeleteTaskPushNotificationConfigMethod = A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod) == null) { - synchronized (A2AServiceGrpc.class) { - if ((getDeleteTaskPushNotificationConfigMethod = A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod) == null) { - A2AServiceGrpc.getDeleteTaskPushNotificationConfigMethod = getDeleteTaskPushNotificationConfigMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "DeleteTaskPushNotificationConfig")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - com.google.protobuf.Empty.getDefaultInstance())) - .setSchemaDescriptor(new A2AServiceMethodDescriptorSupplier("DeleteTaskPushNotificationConfig")) - .build(); - } - } - } - return getDeleteTaskPushNotificationConfigMethod; - } - - /** - * Creates a new async stub that supports all call types for the service - */ - public static A2AServiceStub newStub(io.grpc.Channel channel) { - io.grpc.stub.AbstractStub.StubFactory factory = - new io.grpc.stub.AbstractStub.StubFactory() { - @java.lang.Override - public A2AServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceStub(channel, callOptions); - } - }; - return A2AServiceStub.newStub(factory, channel); - } - - /** - * Creates a new blocking-style stub that supports all types of calls on the service - */ - public static A2AServiceBlockingV2Stub newBlockingV2Stub( - io.grpc.Channel channel) { - io.grpc.stub.AbstractStub.StubFactory factory = - new io.grpc.stub.AbstractStub.StubFactory() { - @java.lang.Override - public A2AServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceBlockingV2Stub(channel, callOptions); - } - }; - return A2AServiceBlockingV2Stub.newStub(factory, channel); - } - - /** - * Creates a new blocking-style stub that supports unary and streaming output calls on the service - */ - public static A2AServiceBlockingStub newBlockingStub( - io.grpc.Channel channel) { - io.grpc.stub.AbstractStub.StubFactory factory = - new io.grpc.stub.AbstractStub.StubFactory() { - @java.lang.Override - public A2AServiceBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceBlockingStub(channel, callOptions); - } - }; - return A2AServiceBlockingStub.newStub(factory, channel); - } - - /** - * Creates a new ListenableFuture-style stub that supports unary calls on the service - */ - public static A2AServiceFutureStub newFutureStub( - io.grpc.Channel channel) { - io.grpc.stub.AbstractStub.StubFactory factory = - new io.grpc.stub.AbstractStub.StubFactory() { - @java.lang.Override - public A2AServiceFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceFutureStub(channel, callOptions); - } - }; - return A2AServiceFutureStub.newStub(factory, channel); - } - - /** - *
-   * A2AService defines the operations of the A2A protocol.
-   * 
- */ - public interface AsyncService { - - /** - *
-     * Send a message to the agent.
-     * 
- */ - default void sendMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSendMessageMethod(), responseObserver); - } - - /** - *
-     * SendStreamingMessage is a streaming version of SendMessage.
-     * 
- */ - default void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSendStreamingMessageMethod(), responseObserver); - } - - /** - *
-     * Get the current state of a task from the agent.
-     * 
- */ - default void getTask(io.a2a.grpc.GetTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetTaskMethod(), responseObserver); - } - - /** - *
-     * List tasks with optional filtering and pagination.
-     * 
- */ - default void listTasks(io.a2a.grpc.ListTasksRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListTasksMethod(), responseObserver); - } - - /** - *
-     * Cancel a task.
-     * 
- */ - default void cancelTask(io.a2a.grpc.CancelTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCancelTaskMethod(), responseObserver); - } - - /** - *
-     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
-     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
-     * 
- */ - default void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getSubscribeToTaskMethod(), responseObserver); - } - - /** - *
-     * Create a push notification config for a task.
-     * 
- */ - default void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCreateTaskPushNotificationConfigMethod(), responseObserver); - } - - /** - *
-     * Get a push notification config for a task.
-     * 
- */ - default void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetTaskPushNotificationConfigMethod(), responseObserver); - } - - /** - *
-     * Get a list of push notifications configured for a task.
-     * 
- */ - default void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getListTaskPushNotificationConfigMethod(), responseObserver); - } - - /** - *
-     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
-     * 
- */ - default void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetExtendedAgentCardMethod(), responseObserver); - } - - /** - *
-     * Delete a push notification config for a task.
-     * 
- */ - default void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getDeleteTaskPushNotificationConfigMethod(), responseObserver); - } - } - - /** - * Base class for the server implementation of the service A2AService. - *
-   * A2AService defines the operations of the A2A protocol.
-   * 
- */ - public static abstract class A2AServiceImplBase - implements io.grpc.BindableService, AsyncService { - - @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { - return A2AServiceGrpc.bindService(this); - } - } - - /** - * A stub to allow clients to do asynchronous rpc calls to service A2AService. - *
-   * A2AService defines the operations of the A2A protocol.
-   * 
- */ - public static final class A2AServiceStub - extends io.grpc.stub.AbstractAsyncStub { - private A2AServiceStub( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - super(channel, callOptions); - } - - @java.lang.Override - protected A2AServiceStub build( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceStub(channel, callOptions); - } - - /** - *
-     * Send a message to the agent.
-     * 
- */ - public void sendMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getSendMessageMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * SendStreamingMessage is a streaming version of SendMessage.
-     * 
- */ - public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncServerStreamingCall( - getChannel().newCall(getSendStreamingMessageMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * Get the current state of a task from the agent.
-     * 
- */ - public void getTask(io.a2a.grpc.GetTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getGetTaskMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * List tasks with optional filtering and pagination.
-     * 
- */ - public void listTasks(io.a2a.grpc.ListTasksRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getListTasksMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * Cancel a task.
-     * 
- */ - public void cancelTask(io.a2a.grpc.CancelTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getCancelTaskMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
-     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
-     * 
- */ - public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncServerStreamingCall( - getChannel().newCall(getSubscribeToTaskMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * Create a push notification config for a task.
-     * 
- */ - public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * Get a push notification config for a task.
-     * 
- */ - public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getGetTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * Get a list of push notifications configured for a task.
-     * 
- */ - public void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getListTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
-     * 
- */ - public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getGetExtendedAgentCardMethod(), getCallOptions()), request, responseObserver); - } - - /** - *
-     * Delete a push notification config for a task.
-     * 
- */ - public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getDeleteTaskPushNotificationConfigMethod(), getCallOptions()), request, responseObserver); - } - } - - /** - * A stub to allow clients to do synchronous rpc calls to service A2AService. - *
-   * A2AService defines the operations of the A2A protocol.
-   * 
- */ - public static final class A2AServiceBlockingV2Stub - extends io.grpc.stub.AbstractBlockingStub { - private A2AServiceBlockingV2Stub( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - super(channel, callOptions); - } - - @java.lang.Override - protected A2AServiceBlockingV2Stub build( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceBlockingV2Stub(channel, callOptions); - } - - /** - *
-     * Send a message to the agent.
-     * 
- */ - public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getSendMessageMethod(), getCallOptions(), request); - } - - /** - *
-     * SendStreamingMessage is a streaming version of SendMessage.
-     * 
- */ - @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") - public io.grpc.stub.BlockingClientCall - sendStreamingMessage(io.a2a.grpc.SendMessageRequest request) { - return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( - getChannel(), getSendStreamingMessageMethod(), getCallOptions(), request); - } - - /** - *
-     * Get the current state of a task from the agent.
-     * 
- */ - public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getGetTaskMethod(), getCallOptions(), request); - } - - /** - *
-     * List tasks with optional filtering and pagination.
-     * 
- */ - public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getListTasksMethod(), getCallOptions(), request); - } - - /** - *
-     * Cancel a task.
-     * 
- */ - public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getCancelTaskMethod(), getCallOptions(), request); - } - - /** - *
-     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
-     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
-     * 
- */ - @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") - public io.grpc.stub.BlockingClientCall - subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request) { - return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( - getChannel(), getSubscribeToTaskMethod(), getCallOptions(), request); - } - - /** - *
-     * Create a push notification config for a task.
-     * 
- */ - public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - - /** - *
-     * Get a push notification config for a task.
-     * 
- */ - public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getGetTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - - /** - *
-     * Get a list of push notifications configured for a task.
-     * 
- */ - public io.a2a.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getListTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - - /** - *
-     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
-     * 
- */ - public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getGetExtendedAgentCardMethod(), getCallOptions(), request); - } - - /** - *
-     * Delete a push notification config for a task.
-     * 
- */ - public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) throws io.grpc.StatusException { - return io.grpc.stub.ClientCalls.blockingV2UnaryCall( - getChannel(), getDeleteTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - } - - /** - * A stub to allow clients to do limited synchronous rpc calls to service A2AService. - *
-   * A2AService defines the operations of the A2A protocol.
-   * 
- */ - public static final class A2AServiceBlockingStub - extends io.grpc.stub.AbstractBlockingStub { - private A2AServiceBlockingStub( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - super(channel, callOptions); - } - - @java.lang.Override - protected A2AServiceBlockingStub build( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceBlockingStub(channel, callOptions); - } - - /** - *
-     * Send a message to the agent.
-     * 
- */ - public io.a2a.grpc.SendMessageResponse sendMessage(io.a2a.grpc.SendMessageRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getSendMessageMethod(), getCallOptions(), request); - } - - /** - *
-     * SendStreamingMessage is a streaming version of SendMessage.
-     * 
- */ - public java.util.Iterator sendStreamingMessage( - io.a2a.grpc.SendMessageRequest request) { - return io.grpc.stub.ClientCalls.blockingServerStreamingCall( - getChannel(), getSendStreamingMessageMethod(), getCallOptions(), request); - } - - /** - *
-     * Get the current state of a task from the agent.
-     * 
- */ - public io.a2a.grpc.Task getTask(io.a2a.grpc.GetTaskRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getGetTaskMethod(), getCallOptions(), request); - } - - /** - *
-     * List tasks with optional filtering and pagination.
-     * 
- */ - public io.a2a.grpc.ListTasksResponse listTasks(io.a2a.grpc.ListTasksRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getListTasksMethod(), getCallOptions(), request); - } - - /** - *
-     * Cancel a task.
-     * 
- */ - public io.a2a.grpc.Task cancelTask(io.a2a.grpc.CancelTaskRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getCancelTaskMethod(), getCallOptions(), request); - } - - /** - *
-     * SubscribeToTask allows subscribing to task updates for tasks not in terminal state.
-     * Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected).
-     * 
- */ - public java.util.Iterator subscribeToTask( - io.a2a.grpc.SubscribeToTaskRequest request) { - return io.grpc.stub.ClientCalls.blockingServerStreamingCall( - getChannel(), getSubscribeToTaskMethod(), getCallOptions(), request); - } - - /** - *
-     * Create a push notification config for a task.
-     * 
- */ - public io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getCreateTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - - /** - *
-     * Get a push notification config for a task.
-     * 
- */ - public io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getGetTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - - /** - *
-     * Get a list of push notifications configured for a task.
-     * 
- */ - public io.a2a.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getListTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - - /** - *
-     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
-     * 
- */ - public io.a2a.grpc.AgentCard getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getGetExtendedAgentCardMethod(), getCallOptions(), request); - } - - /** - *
-     * Delete a push notification config for a task.
-     * 
- */ - public com.google.protobuf.Empty deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getDeleteTaskPushNotificationConfigMethod(), getCallOptions(), request); - } - } - - /** - * A stub to allow clients to do ListenableFuture-style rpc calls to service A2AService. - *
-   * A2AService defines the operations of the A2A protocol.
-   * 
- */ - public static final class A2AServiceFutureStub - extends io.grpc.stub.AbstractFutureStub { - private A2AServiceFutureStub( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - super(channel, callOptions); - } - - @java.lang.Override - protected A2AServiceFutureStub build( - io.grpc.Channel channel, io.grpc.CallOptions callOptions) { - return new A2AServiceFutureStub(channel, callOptions); - } - - /** - *
-     * Send a message to the agent.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture sendMessage( - io.a2a.grpc.SendMessageRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getSendMessageMethod(), getCallOptions()), request); - } - - /** - *
-     * Get the current state of a task from the agent.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture getTask( - io.a2a.grpc.GetTaskRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getGetTaskMethod(), getCallOptions()), request); - } - - /** - *
-     * List tasks with optional filtering and pagination.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture listTasks( - io.a2a.grpc.ListTasksRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getListTasksMethod(), getCallOptions()), request); - } - - /** - *
-     * Cancel a task.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture cancelTask( - io.a2a.grpc.CancelTaskRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getCancelTaskMethod(), getCallOptions()), request); - } - - /** - *
-     * Create a push notification config for a task.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture createTaskPushNotificationConfig( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getCreateTaskPushNotificationConfigMethod(), getCallOptions()), request); - } - - /** - *
-     * Get a push notification config for a task.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture getTaskPushNotificationConfig( - io.a2a.grpc.GetTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getGetTaskPushNotificationConfigMethod(), getCallOptions()), request); - } - - /** - *
-     * Get a list of push notifications configured for a task.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture listTaskPushNotificationConfig( - io.a2a.grpc.ListTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getListTaskPushNotificationConfigMethod(), getCallOptions()), request); - } - - /** - *
-     * GetExtendedAgentCard returns the extended agent card for authenticated agents.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture getExtendedAgentCard( - io.a2a.grpc.GetExtendedAgentCardRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getGetExtendedAgentCardMethod(), getCallOptions()), request); - } - - /** - *
-     * Delete a push notification config for a task.
-     * 
- */ - public com.google.common.util.concurrent.ListenableFuture deleteTaskPushNotificationConfig( - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getDeleteTaskPushNotificationConfigMethod(), getCallOptions()), request); - } - } - - private static final int METHODID_SEND_MESSAGE = 0; - private static final int METHODID_SEND_STREAMING_MESSAGE = 1; - private static final int METHODID_GET_TASK = 2; - private static final int METHODID_LIST_TASKS = 3; - private static final int METHODID_CANCEL_TASK = 4; - private static final int METHODID_SUBSCRIBE_TO_TASK = 5; - private static final int METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG = 6; - private static final int METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG = 7; - private static final int METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG = 8; - private static final int METHODID_GET_EXTENDED_AGENT_CARD = 9; - private static final int METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG = 10; - - private static final class MethodHandlers implements - io.grpc.stub.ServerCalls.UnaryMethod, - io.grpc.stub.ServerCalls.ServerStreamingMethod, - io.grpc.stub.ServerCalls.ClientStreamingMethod, - io.grpc.stub.ServerCalls.BidiStreamingMethod { - private final AsyncService serviceImpl; - private final int methodId; - - MethodHandlers(AsyncService serviceImpl, int methodId) { - this.serviceImpl = serviceImpl; - this.methodId = methodId; - } - - @java.lang.Override - @java.lang.SuppressWarnings("unchecked") - public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { - switch (methodId) { - case METHODID_SEND_MESSAGE: - serviceImpl.sendMessage((io.a2a.grpc.SendMessageRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_SEND_STREAMING_MESSAGE: - serviceImpl.sendStreamingMessage((io.a2a.grpc.SendMessageRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_GET_TASK: - serviceImpl.getTask((io.a2a.grpc.GetTaskRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_LIST_TASKS: - serviceImpl.listTasks((io.a2a.grpc.ListTasksRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_CANCEL_TASK: - serviceImpl.cancelTask((io.a2a.grpc.CancelTaskRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_SUBSCRIBE_TO_TASK: - serviceImpl.subscribeToTask((io.a2a.grpc.SubscribeToTaskRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.createTaskPushNotificationConfig((io.a2a.grpc.CreateTaskPushNotificationConfigRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.getTaskPushNotificationConfig((io.a2a.grpc.GetTaskPushNotificationConfigRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.listTaskPushNotificationConfig((io.a2a.grpc.ListTaskPushNotificationConfigRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_GET_EXTENDED_AGENT_CARD: - serviceImpl.getExtendedAgentCard((io.a2a.grpc.GetExtendedAgentCardRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - case METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG: - serviceImpl.deleteTaskPushNotificationConfig((io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; - default: - throw new AssertionError(); - } - } - - @java.lang.Override - @java.lang.SuppressWarnings("unchecked") - public io.grpc.stub.StreamObserver invoke( - io.grpc.stub.StreamObserver responseObserver) { - switch (methodId) { - default: - throw new AssertionError(); - } - } - } - - public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) { - return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) - .addMethod( - getSendMessageMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.SendMessageRequest, - io.a2a.grpc.SendMessageResponse>( - service, METHODID_SEND_MESSAGE))) - .addMethod( - getSendStreamingMessageMethod(), - io.grpc.stub.ServerCalls.asyncServerStreamingCall( - new MethodHandlers< - io.a2a.grpc.SendMessageRequest, - io.a2a.grpc.StreamResponse>( - service, METHODID_SEND_STREAMING_MESSAGE))) - .addMethod( - getGetTaskMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.GetTaskRequest, - io.a2a.grpc.Task>( - service, METHODID_GET_TASK))) - .addMethod( - getListTasksMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.ListTasksRequest, - io.a2a.grpc.ListTasksResponse>( - service, METHODID_LIST_TASKS))) - .addMethod( - getCancelTaskMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.CancelTaskRequest, - io.a2a.grpc.Task>( - service, METHODID_CANCEL_TASK))) - .addMethod( - getSubscribeToTaskMethod(), - io.grpc.stub.ServerCalls.asyncServerStreamingCall( - new MethodHandlers< - io.a2a.grpc.SubscribeToTaskRequest, - io.a2a.grpc.StreamResponse>( - service, METHODID_SUBSCRIBE_TO_TASK))) - .addMethod( - getCreateTaskPushNotificationConfigMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.CreateTaskPushNotificationConfigRequest, - io.a2a.grpc.TaskPushNotificationConfig>( - service, METHODID_CREATE_TASK_PUSH_NOTIFICATION_CONFIG))) - .addMethod( - getGetTaskPushNotificationConfigMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.GetTaskPushNotificationConfigRequest, - io.a2a.grpc.TaskPushNotificationConfig>( - service, METHODID_GET_TASK_PUSH_NOTIFICATION_CONFIG))) - .addMethod( - getListTaskPushNotificationConfigMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.ListTaskPushNotificationConfigRequest, - io.a2a.grpc.ListTaskPushNotificationConfigResponse>( - service, METHODID_LIST_TASK_PUSH_NOTIFICATION_CONFIG))) - .addMethod( - getGetExtendedAgentCardMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.GetExtendedAgentCardRequest, - io.a2a.grpc.AgentCard>( - service, METHODID_GET_EXTENDED_AGENT_CARD))) - .addMethod( - getDeleteTaskPushNotificationConfigMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest, - com.google.protobuf.Empty>( - service, METHODID_DELETE_TASK_PUSH_NOTIFICATION_CONFIG))) - .build(); - } - - private static abstract class A2AServiceBaseDescriptorSupplier - implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { - A2AServiceBaseDescriptorSupplier() {} - - @java.lang.Override - public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { - return io.a2a.grpc.A2A.getDescriptor(); - } - - @java.lang.Override - public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { - return getFileDescriptor().findServiceByName("A2AService"); - } - } - - private static final class A2AServiceFileDescriptorSupplier - extends A2AServiceBaseDescriptorSupplier { - A2AServiceFileDescriptorSupplier() {} - } - - private static final class A2AServiceMethodDescriptorSupplier - extends A2AServiceBaseDescriptorSupplier - implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { - private final java.lang.String methodName; - - A2AServiceMethodDescriptorSupplier(java.lang.String methodName) { - this.methodName = methodName; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { - return getServiceDescriptor().findMethodByName(methodName); - } - } - - private static volatile io.grpc.ServiceDescriptor serviceDescriptor; - - public static io.grpc.ServiceDescriptor getServiceDescriptor() { - io.grpc.ServiceDescriptor result = serviceDescriptor; - if (result == null) { - synchronized (A2AServiceGrpc.class) { - result = serviceDescriptor; - if (result == null) { - serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) - .setSchemaDescriptor(new A2AServiceFileDescriptorSupplier()) - .addMethod(getSendMessageMethod()) - .addMethod(getSendStreamingMessageMethod()) - .addMethod(getGetTaskMethod()) - .addMethod(getListTasksMethod()) - .addMethod(getCancelTaskMethod()) - .addMethod(getSubscribeToTaskMethod()) - .addMethod(getCreateTaskPushNotificationConfigMethod()) - .addMethod(getGetTaskPushNotificationConfigMethod()) - .addMethod(getListTaskPushNotificationConfigMethod()) - .addMethod(getGetExtendedAgentCardMethod()) - .addMethod(getDeleteTaskPushNotificationConfigMethod()) - .build(); - } - } - } - return result; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java deleted file mode 100644 index a189729df..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecurityScheme.java +++ /dev/null @@ -1,868 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:APIKeySecurityScheme]
- * Defines a security scheme using an API key.
- * 
- * - * Protobuf type {@code a2a.v1.APIKeySecurityScheme} - */ -@com.google.protobuf.Generated -public final class APIKeySecurityScheme extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.APIKeySecurityScheme) - APIKeySecuritySchemeOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "APIKeySecurityScheme"); - } - // Use APIKeySecurityScheme.newBuilder() to construct. - private APIKeySecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private APIKeySecurityScheme() { - description_ = ""; - location_ = ""; - name_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.APIKeySecurityScheme.class, io.a2a.grpc.APIKeySecurityScheme.Builder.class); - } - - public static final int DESCRIPTION_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int LOCATION_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object location_ = ""; - /** - *
-   * The location of the API key. Valid values are "query", "header", or "cookie".
-   * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The location. - */ - @java.lang.Override - public java.lang.String getLocation() { - java.lang.Object ref = location_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - location_ = s; - return s; - } - } - /** - *
-   * The location of the API key. Valid values are "query", "header", or "cookie".
-   * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for location. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getLocationBytes() { - java.lang.Object ref = location_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - location_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int NAME_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; - /** - *
-   * The name of the header, query, or cookie parameter to be used.
-   * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } - } - /** - *
-   * The name of the header, query, or cookie parameter to be used.
-   * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(location_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, location_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, name_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(location_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, location_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, name_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.APIKeySecurityScheme)) { - return super.equals(obj); - } - io.a2a.grpc.APIKeySecurityScheme other = (io.a2a.grpc.APIKeySecurityScheme) obj; - - if (!getDescription() - .equals(other.getDescription())) return false; - if (!getLocation() - .equals(other.getLocation())) return false; - if (!getName() - .equals(other.getName())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - hash = (37 * hash) + LOCATION_FIELD_NUMBER; - hash = (53 * hash) + getLocation().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.APIKeySecurityScheme parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.APIKeySecurityScheme parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.APIKeySecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.APIKeySecurityScheme prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:APIKeySecurityScheme]
-   * Defines a security scheme using an API key.
-   * 
- * - * Protobuf type {@code a2a.v1.APIKeySecurityScheme} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.APIKeySecurityScheme) - io.a2a.grpc.APIKeySecuritySchemeOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.APIKeySecurityScheme.class, io.a2a.grpc.APIKeySecurityScheme.Builder.class); - } - - // Construct using io.a2a.grpc.APIKeySecurityScheme.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - description_ = ""; - location_ = ""; - name_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_APIKeySecurityScheme_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.APIKeySecurityScheme getDefaultInstanceForType() { - return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.APIKeySecurityScheme build() { - io.a2a.grpc.APIKeySecurityScheme result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.APIKeySecurityScheme buildPartial() { - io.a2a.grpc.APIKeySecurityScheme result = new io.a2a.grpc.APIKeySecurityScheme(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.APIKeySecurityScheme result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.description_ = description_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.location_ = location_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.name_ = name_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.APIKeySecurityScheme) { - return mergeFrom((io.a2a.grpc.APIKeySecurityScheme)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.APIKeySecurityScheme other) { - if (other == io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance()) return this; - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getLocation().isEmpty()) { - location_ = other.location_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getName().isEmpty()) { - name_ = other.name_; - bitField0_ |= 0x00000004; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - location_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object description_ = ""; - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object location_ = ""; - /** - *
-     * The location of the API key. Valid values are "query", "header", or "cookie".
-     * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The location. - */ - public java.lang.String getLocation() { - java.lang.Object ref = location_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - location_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The location of the API key. Valid values are "query", "header", or "cookie".
-     * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for location. - */ - public com.google.protobuf.ByteString - getLocationBytes() { - java.lang.Object ref = location_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - location_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The location of the API key. Valid values are "query", "header", or "cookie".
-     * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The location to set. - * @return This builder for chaining. - */ - public Builder setLocation( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - location_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The location of the API key. Valid values are "query", "header", or "cookie".
-     * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearLocation() { - location_ = getDefaultInstance().getLocation(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The location of the API key. Valid values are "query", "header", or "cookie".
-     * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for location to set. - * @return This builder for chaining. - */ - public Builder setLocationBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - location_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object name_ = ""; - /** - *
-     * The name of the header, query, or cookie parameter to be used.
-     * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The name of the header, query, or cookie parameter to be used.
-     * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The name of the header, query, or cookie parameter to be used.
-     * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The name to set. - * @return This builder for chaining. - */ - public Builder setName( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - name_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The name of the header, query, or cookie parameter to be used.
-     * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The name of the header, query, or cookie parameter to be used.
-     * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for name to set. - * @return This builder for chaining. - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - name_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.APIKeySecurityScheme) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.APIKeySecurityScheme) - private static final io.a2a.grpc.APIKeySecurityScheme DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.APIKeySecurityScheme(); - } - - public static io.a2a.grpc.APIKeySecurityScheme getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public APIKeySecurityScheme parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.APIKeySecurityScheme getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java deleted file mode 100644 index 757464225..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/APIKeySecuritySchemeOrBuilder.java +++ /dev/null @@ -1,72 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface APIKeySecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.APIKeySecurityScheme) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * The location of the API key. Valid values are "query", "header", or "cookie".
-   * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The location. - */ - java.lang.String getLocation(); - /** - *
-   * The location of the API key. Valid values are "query", "header", or "cookie".
-   * 
- * - * string location = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for location. - */ - com.google.protobuf.ByteString - getLocationBytes(); - - /** - *
-   * The name of the header, query, or cookie parameter to be used.
-   * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - java.lang.String getName(); - /** - *
-   * The name of the header, query, or cookie parameter to be used.
-   * 
- * - * string name = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - com.google.protobuf.ByteString - getNameBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java deleted file mode 100644 index 84796af69..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilities.java +++ /dev/null @@ -1,1164 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AgentCapabilities]
- * Defines optional capabilities supported by an agent.
- * 
- * - * Protobuf type {@code a2a.v1.AgentCapabilities} - */ -@com.google.protobuf.Generated -public final class AgentCapabilities extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentCapabilities) - AgentCapabilitiesOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AgentCapabilities"); - } - // Use AgentCapabilities.newBuilder() to construct. - private AgentCapabilities(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AgentCapabilities() { - extensions_ = java.util.Collections.emptyList(); - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentCapabilities.class, io.a2a.grpc.AgentCapabilities.Builder.class); - } - - private int bitField0_; - public static final int STREAMING_FIELD_NUMBER = 1; - private boolean streaming_ = false; - /** - *
-   * Indicates if the agent supports streaming responses.
-   * 
- * - * optional bool streaming = 1; - * @return Whether the streaming field is set. - */ - @java.lang.Override - public boolean hasStreaming() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * Indicates if the agent supports streaming responses.
-   * 
- * - * optional bool streaming = 1; - * @return The streaming. - */ - @java.lang.Override - public boolean getStreaming() { - return streaming_; - } - - public static final int PUSH_NOTIFICATIONS_FIELD_NUMBER = 2; - private boolean pushNotifications_ = false; - /** - *
-   * Indicates if the agent supports sending push notifications for asynchronous task updates.
-   * 
- * - * optional bool push_notifications = 2; - * @return Whether the pushNotifications field is set. - */ - @java.lang.Override - public boolean hasPushNotifications() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * Indicates if the agent supports sending push notifications for asynchronous task updates.
-   * 
- * - * optional bool push_notifications = 2; - * @return The pushNotifications. - */ - @java.lang.Override - public boolean getPushNotifications() { - return pushNotifications_; - } - - public static final int EXTENSIONS_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private java.util.List extensions_; - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - @java.lang.Override - public java.util.List getExtensionsList() { - return extensions_; - } - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - @java.lang.Override - public java.util.List - getExtensionsOrBuilderList() { - return extensions_; - } - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - @java.lang.Override - public int getExtensionsCount() { - return extensions_.size(); - } - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - @java.lang.Override - public io.a2a.grpc.AgentExtension getExtensions(int index) { - return extensions_.get(index); - } - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - @java.lang.Override - public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( - int index) { - return extensions_.get(index); - } - - public static final int EXTENDED_AGENT_CARD_FIELD_NUMBER = 5; - private boolean extendedAgentCard_ = false; - /** - *
-   * Indicates if the agent supports providing an extended agent card when authenticated.
-   * 
- * - * optional bool extended_agent_card = 5; - * @return Whether the extendedAgentCard field is set. - */ - @java.lang.Override - public boolean hasExtendedAgentCard() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-   * Indicates if the agent supports providing an extended agent card when authenticated.
-   * 
- * - * optional bool extended_agent_card = 5; - * @return The extendedAgentCard. - */ - @java.lang.Override - public boolean getExtendedAgentCard() { - return extendedAgentCard_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (((bitField0_ & 0x00000001) != 0)) { - output.writeBool(1, streaming_); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeBool(2, pushNotifications_); - } - for (int i = 0; i < extensions_.size(); i++) { - output.writeMessage(3, extensions_.get(i)); - } - if (((bitField0_ & 0x00000004) != 0)) { - output.writeBool(5, extendedAgentCard_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(1, streaming_); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(2, pushNotifications_); - } - for (int i = 0; i < extensions_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, extensions_.get(i)); - } - if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(5, extendedAgentCard_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AgentCapabilities)) { - return super.equals(obj); - } - io.a2a.grpc.AgentCapabilities other = (io.a2a.grpc.AgentCapabilities) obj; - - if (hasStreaming() != other.hasStreaming()) return false; - if (hasStreaming()) { - if (getStreaming() - != other.getStreaming()) return false; - } - if (hasPushNotifications() != other.hasPushNotifications()) return false; - if (hasPushNotifications()) { - if (getPushNotifications() - != other.getPushNotifications()) return false; - } - if (!getExtensionsList() - .equals(other.getExtensionsList())) return false; - if (hasExtendedAgentCard() != other.hasExtendedAgentCard()) return false; - if (hasExtendedAgentCard()) { - if (getExtendedAgentCard() - != other.getExtendedAgentCard()) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (hasStreaming()) { - hash = (37 * hash) + STREAMING_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getStreaming()); - } - if (hasPushNotifications()) { - hash = (37 * hash) + PUSH_NOTIFICATIONS_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getPushNotifications()); - } - if (getExtensionsCount() > 0) { - hash = (37 * hash) + EXTENSIONS_FIELD_NUMBER; - hash = (53 * hash) + getExtensionsList().hashCode(); - } - if (hasExtendedAgentCard()) { - hash = (37 * hash) + EXTENDED_AGENT_CARD_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getExtendedAgentCard()); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AgentCapabilities parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCapabilities parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCapabilities parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCapabilities parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCapabilities parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCapabilities parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCapabilities parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentCapabilities parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AgentCapabilities parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AgentCapabilities parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AgentCapabilities parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentCapabilities parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AgentCapabilities prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AgentCapabilities]
-   * Defines optional capabilities supported by an agent.
-   * 
- * - * Protobuf type {@code a2a.v1.AgentCapabilities} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCapabilities) - io.a2a.grpc.AgentCapabilitiesOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentCapabilities.class, io.a2a.grpc.AgentCapabilities.Builder.class); - } - - // Construct using io.a2a.grpc.AgentCapabilities.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - streaming_ = false; - pushNotifications_ = false; - if (extensionsBuilder_ == null) { - extensions_ = java.util.Collections.emptyList(); - } else { - extensions_ = null; - extensionsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000004); - extendedAgentCard_ = false; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCapabilities_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AgentCapabilities getDefaultInstanceForType() { - return io.a2a.grpc.AgentCapabilities.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AgentCapabilities build() { - io.a2a.grpc.AgentCapabilities result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AgentCapabilities buildPartial() { - io.a2a.grpc.AgentCapabilities result = new io.a2a.grpc.AgentCapabilities(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.AgentCapabilities result) { - if (extensionsBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0)) { - extensions_ = java.util.Collections.unmodifiableList(extensions_); - bitField0_ = (bitField0_ & ~0x00000004); - } - result.extensions_ = extensions_; - } else { - result.extensions_ = extensionsBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.AgentCapabilities result) { - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.streaming_ = streaming_; - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.pushNotifications_ = pushNotifications_; - to_bitField0_ |= 0x00000002; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.extendedAgentCard_ = extendedAgentCard_; - to_bitField0_ |= 0x00000004; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AgentCapabilities) { - return mergeFrom((io.a2a.grpc.AgentCapabilities)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AgentCapabilities other) { - if (other == io.a2a.grpc.AgentCapabilities.getDefaultInstance()) return this; - if (other.hasStreaming()) { - setStreaming(other.getStreaming()); - } - if (other.hasPushNotifications()) { - setPushNotifications(other.getPushNotifications()); - } - if (extensionsBuilder_ == null) { - if (!other.extensions_.isEmpty()) { - if (extensions_.isEmpty()) { - extensions_ = other.extensions_; - bitField0_ = (bitField0_ & ~0x00000004); - } else { - ensureExtensionsIsMutable(); - extensions_.addAll(other.extensions_); - } - onChanged(); - } - } else { - if (!other.extensions_.isEmpty()) { - if (extensionsBuilder_.isEmpty()) { - extensionsBuilder_.dispose(); - extensionsBuilder_ = null; - extensions_ = other.extensions_; - bitField0_ = (bitField0_ & ~0x00000004); - extensionsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetExtensionsFieldBuilder() : null; - } else { - extensionsBuilder_.addAllMessages(other.extensions_); - } - } - } - if (other.hasExtendedAgentCard()) { - setExtendedAgentCard(other.getExtendedAgentCard()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 8: { - streaming_ = input.readBool(); - bitField0_ |= 0x00000001; - break; - } // case 8 - case 16: { - pushNotifications_ = input.readBool(); - bitField0_ |= 0x00000002; - break; - } // case 16 - case 26: { - io.a2a.grpc.AgentExtension m = - input.readMessage( - io.a2a.grpc.AgentExtension.parser(), - extensionRegistry); - if (extensionsBuilder_ == null) { - ensureExtensionsIsMutable(); - extensions_.add(m); - } else { - extensionsBuilder_.addMessage(m); - } - break; - } // case 26 - case 40: { - extendedAgentCard_ = input.readBool(); - bitField0_ |= 0x00000008; - break; - } // case 40 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private boolean streaming_ ; - /** - *
-     * Indicates if the agent supports streaming responses.
-     * 
- * - * optional bool streaming = 1; - * @return Whether the streaming field is set. - */ - @java.lang.Override - public boolean hasStreaming() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-     * Indicates if the agent supports streaming responses.
-     * 
- * - * optional bool streaming = 1; - * @return The streaming. - */ - @java.lang.Override - public boolean getStreaming() { - return streaming_; - } - /** - *
-     * Indicates if the agent supports streaming responses.
-     * 
- * - * optional bool streaming = 1; - * @param value The streaming to set. - * @return This builder for chaining. - */ - public Builder setStreaming(boolean value) { - - streaming_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Indicates if the agent supports streaming responses.
-     * 
- * - * optional bool streaming = 1; - * @return This builder for chaining. - */ - public Builder clearStreaming() { - bitField0_ = (bitField0_ & ~0x00000001); - streaming_ = false; - onChanged(); - return this; - } - - private boolean pushNotifications_ ; - /** - *
-     * Indicates if the agent supports sending push notifications for asynchronous task updates.
-     * 
- * - * optional bool push_notifications = 2; - * @return Whether the pushNotifications field is set. - */ - @java.lang.Override - public boolean hasPushNotifications() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-     * Indicates if the agent supports sending push notifications for asynchronous task updates.
-     * 
- * - * optional bool push_notifications = 2; - * @return The pushNotifications. - */ - @java.lang.Override - public boolean getPushNotifications() { - return pushNotifications_; - } - /** - *
-     * Indicates if the agent supports sending push notifications for asynchronous task updates.
-     * 
- * - * optional bool push_notifications = 2; - * @param value The pushNotifications to set. - * @return This builder for chaining. - */ - public Builder setPushNotifications(boolean value) { - - pushNotifications_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Indicates if the agent supports sending push notifications for asynchronous task updates.
-     * 
- * - * optional bool push_notifications = 2; - * @return This builder for chaining. - */ - public Builder clearPushNotifications() { - bitField0_ = (bitField0_ & ~0x00000002); - pushNotifications_ = false; - onChanged(); - return this; - } - - private java.util.List extensions_ = - java.util.Collections.emptyList(); - private void ensureExtensionsIsMutable() { - if (!((bitField0_ & 0x00000004) != 0)) { - extensions_ = new java.util.ArrayList(extensions_); - bitField0_ |= 0x00000004; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentExtension, io.a2a.grpc.AgentExtension.Builder, io.a2a.grpc.AgentExtensionOrBuilder> extensionsBuilder_; - - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public java.util.List getExtensionsList() { - if (extensionsBuilder_ == null) { - return java.util.Collections.unmodifiableList(extensions_); - } else { - return extensionsBuilder_.getMessageList(); - } - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public int getExtensionsCount() { - if (extensionsBuilder_ == null) { - return extensions_.size(); - } else { - return extensionsBuilder_.getCount(); - } - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public io.a2a.grpc.AgentExtension getExtensions(int index) { - if (extensionsBuilder_ == null) { - return extensions_.get(index); - } else { - return extensionsBuilder_.getMessage(index); - } - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder setExtensions( - int index, io.a2a.grpc.AgentExtension value) { - if (extensionsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureExtensionsIsMutable(); - extensions_.set(index, value); - onChanged(); - } else { - extensionsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder setExtensions( - int index, io.a2a.grpc.AgentExtension.Builder builderForValue) { - if (extensionsBuilder_ == null) { - ensureExtensionsIsMutable(); - extensions_.set(index, builderForValue.build()); - onChanged(); - } else { - extensionsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder addExtensions(io.a2a.grpc.AgentExtension value) { - if (extensionsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureExtensionsIsMutable(); - extensions_.add(value); - onChanged(); - } else { - extensionsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder addExtensions( - int index, io.a2a.grpc.AgentExtension value) { - if (extensionsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureExtensionsIsMutable(); - extensions_.add(index, value); - onChanged(); - } else { - extensionsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder addExtensions( - io.a2a.grpc.AgentExtension.Builder builderForValue) { - if (extensionsBuilder_ == null) { - ensureExtensionsIsMutable(); - extensions_.add(builderForValue.build()); - onChanged(); - } else { - extensionsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder addExtensions( - int index, io.a2a.grpc.AgentExtension.Builder builderForValue) { - if (extensionsBuilder_ == null) { - ensureExtensionsIsMutable(); - extensions_.add(index, builderForValue.build()); - onChanged(); - } else { - extensionsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder addAllExtensions( - java.lang.Iterable values) { - if (extensionsBuilder_ == null) { - ensureExtensionsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, extensions_); - onChanged(); - } else { - extensionsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder clearExtensions() { - if (extensionsBuilder_ == null) { - extensions_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - } else { - extensionsBuilder_.clear(); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public Builder removeExtensions(int index) { - if (extensionsBuilder_ == null) { - ensureExtensionsIsMutable(); - extensions_.remove(index); - onChanged(); - } else { - extensionsBuilder_.remove(index); - } - return this; - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public io.a2a.grpc.AgentExtension.Builder getExtensionsBuilder( - int index) { - return internalGetExtensionsFieldBuilder().getBuilder(index); - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( - int index) { - if (extensionsBuilder_ == null) { - return extensions_.get(index); } else { - return extensionsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public java.util.List - getExtensionsOrBuilderList() { - if (extensionsBuilder_ != null) { - return extensionsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(extensions_); - } - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder() { - return internalGetExtensionsFieldBuilder().addBuilder( - io.a2a.grpc.AgentExtension.getDefaultInstance()); - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public io.a2a.grpc.AgentExtension.Builder addExtensionsBuilder( - int index) { - return internalGetExtensionsFieldBuilder().addBuilder( - index, io.a2a.grpc.AgentExtension.getDefaultInstance()); - } - /** - *
-     * A list of protocol extensions supported by the agent.
-     * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - public java.util.List - getExtensionsBuilderList() { - return internalGetExtensionsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentExtension, io.a2a.grpc.AgentExtension.Builder, io.a2a.grpc.AgentExtensionOrBuilder> - internalGetExtensionsFieldBuilder() { - if (extensionsBuilder_ == null) { - extensionsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentExtension, io.a2a.grpc.AgentExtension.Builder, io.a2a.grpc.AgentExtensionOrBuilder>( - extensions_, - ((bitField0_ & 0x00000004) != 0), - getParentForChildren(), - isClean()); - extensions_ = null; - } - return extensionsBuilder_; - } - - private boolean extendedAgentCard_ ; - /** - *
-     * Indicates if the agent supports providing an extended agent card when authenticated.
-     * 
- * - * optional bool extended_agent_card = 5; - * @return Whether the extendedAgentCard field is set. - */ - @java.lang.Override - public boolean hasExtendedAgentCard() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * Indicates if the agent supports providing an extended agent card when authenticated.
-     * 
- * - * optional bool extended_agent_card = 5; - * @return The extendedAgentCard. - */ - @java.lang.Override - public boolean getExtendedAgentCard() { - return extendedAgentCard_; - } - /** - *
-     * Indicates if the agent supports providing an extended agent card when authenticated.
-     * 
- * - * optional bool extended_agent_card = 5; - * @param value The extendedAgentCard to set. - * @return This builder for chaining. - */ - public Builder setExtendedAgentCard(boolean value) { - - extendedAgentCard_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Indicates if the agent supports providing an extended agent card when authenticated.
-     * 
- * - * optional bool extended_agent_card = 5; - * @return This builder for chaining. - */ - public Builder clearExtendedAgentCard() { - bitField0_ = (bitField0_ & ~0x00000008); - extendedAgentCard_ = false; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCapabilities) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AgentCapabilities) - private static final io.a2a.grpc.AgentCapabilities DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AgentCapabilities(); - } - - public static io.a2a.grpc.AgentCapabilities getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AgentCapabilities parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AgentCapabilities getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java deleted file mode 100644 index 05c90e4d2..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCapabilitiesOrBuilder.java +++ /dev/null @@ -1,113 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AgentCapabilitiesOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCapabilities) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Indicates if the agent supports streaming responses.
-   * 
- * - * optional bool streaming = 1; - * @return Whether the streaming field is set. - */ - boolean hasStreaming(); - /** - *
-   * Indicates if the agent supports streaming responses.
-   * 
- * - * optional bool streaming = 1; - * @return The streaming. - */ - boolean getStreaming(); - - /** - *
-   * Indicates if the agent supports sending push notifications for asynchronous task updates.
-   * 
- * - * optional bool push_notifications = 2; - * @return Whether the pushNotifications field is set. - */ - boolean hasPushNotifications(); - /** - *
-   * Indicates if the agent supports sending push notifications for asynchronous task updates.
-   * 
- * - * optional bool push_notifications = 2; - * @return The pushNotifications. - */ - boolean getPushNotifications(); - - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - java.util.List - getExtensionsList(); - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - io.a2a.grpc.AgentExtension getExtensions(int index); - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - int getExtensionsCount(); - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - java.util.List - getExtensionsOrBuilderList(); - /** - *
-   * A list of protocol extensions supported by the agent.
-   * 
- * - * repeated .a2a.v1.AgentExtension extensions = 3; - */ - io.a2a.grpc.AgentExtensionOrBuilder getExtensionsOrBuilder( - int index); - - /** - *
-   * Indicates if the agent supports providing an extended agent card when authenticated.
-   * 
- * - * optional bool extended_agent_card = 5; - * @return Whether the extendedAgentCard field is set. - */ - boolean hasExtendedAgentCard(); - /** - *
-   * Indicates if the agent supports providing an extended agent card when authenticated.
-   * 
- * - * optional bool extended_agent_card = 5; - * @return The extendedAgentCard. - */ - boolean getExtendedAgentCard(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java deleted file mode 100644 index 2b06f54b8..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCard.java +++ /dev/null @@ -1,4446 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AgentCard]
- * AgentCard is a self-describing manifest for an agent. It provides essential
- * metadata including the agent's identity, capabilities, skills, supported
- * communication methods, and security requirements.
- * Next ID: 20
- * 
- * - * Protobuf type {@code a2a.v1.AgentCard} - */ -@com.google.protobuf.Generated -public final class AgentCard extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentCard) - AgentCardOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AgentCard"); - } - // Use AgentCard.newBuilder() to construct. - private AgentCard(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AgentCard() { - name_ = ""; - description_ = ""; - supportedInterfaces_ = java.util.Collections.emptyList(); - version_ = ""; - documentationUrl_ = ""; - securityRequirements_ = java.util.Collections.emptyList(); - defaultInputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - defaultOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - skills_ = java.util.Collections.emptyList(); - signatures_ = java.util.Collections.emptyList(); - iconUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 8: - return internalGetSecuritySchemes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentCard.class, io.a2a.grpc.AgentCard.Builder.class); - } - - private int bitField0_; - public static final int NAME_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; - /** - *
-   * A human readable name for the agent.
-   * Example: "Recipe Agent"
-   * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } - } - /** - *
-   * A human readable name for the agent.
-   * Example: "Recipe Agent"
-   * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int DESCRIPTION_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * A human-readable description of the agent, assisting users and other agents
-   * in understanding its purpose.
-   * Example: "Agent that helps users with recipes and cooking."
-   * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * A human-readable description of the agent, assisting users and other agents
-   * in understanding its purpose.
-   * Example: "Agent that helps users with recipes and cooking."
-   * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SUPPORTED_INTERFACES_FIELD_NUMBER = 19; - @SuppressWarnings("serial") - private java.util.List supportedInterfaces_; - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List getSupportedInterfacesList() { - return supportedInterfaces_; - } - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List - getSupportedInterfacesOrBuilderList() { - return supportedInterfaces_; - } - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public int getSupportedInterfacesCount() { - return supportedInterfaces_.size(); - } - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { - return supportedInterfaces_.get(index); - } - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( - int index) { - return supportedInterfaces_.get(index); - } - - public static final int PROVIDER_FIELD_NUMBER = 4; - private io.a2a.grpc.AgentProvider provider_; - /** - *
-   * The service provider of the agent.
-   * 
- * - * .a2a.v1.AgentProvider provider = 4; - * @return Whether the provider field is set. - */ - @java.lang.Override - public boolean hasProvider() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The service provider of the agent.
-   * 
- * - * .a2a.v1.AgentProvider provider = 4; - * @return The provider. - */ - @java.lang.Override - public io.a2a.grpc.AgentProvider getProvider() { - return provider_ == null ? io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_; - } - /** - *
-   * The service provider of the agent.
-   * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - @java.lang.Override - public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() { - return provider_ == null ? io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_; - } - - public static final int VERSION_FIELD_NUMBER = 5; - @SuppressWarnings("serial") - private volatile java.lang.Object version_ = ""; - /** - *
-   * The version of the agent.
-   * Example: "1.0.0"
-   * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The version. - */ - @java.lang.Override - public java.lang.String getVersion() { - java.lang.Object ref = version_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - version_ = s; - return s; - } - } - /** - *
-   * The version of the agent.
-   * Example: "1.0.0"
-   * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for version. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getVersionBytes() { - java.lang.Object ref = version_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - version_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int DOCUMENTATION_URL_FIELD_NUMBER = 6; - @SuppressWarnings("serial") - private volatile java.lang.Object documentationUrl_ = ""; - /** - *
-   * A url to provide additional documentation about the agent.
-   * 
- * - * optional string documentation_url = 6; - * @return Whether the documentationUrl field is set. - */ - @java.lang.Override - public boolean hasDocumentationUrl() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * A url to provide additional documentation about the agent.
-   * 
- * - * optional string documentation_url = 6; - * @return The documentationUrl. - */ - @java.lang.Override - public java.lang.String getDocumentationUrl() { - java.lang.Object ref = documentationUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - documentationUrl_ = s; - return s; - } - } - /** - *
-   * A url to provide additional documentation about the agent.
-   * 
- * - * optional string documentation_url = 6; - * @return The bytes for documentationUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDocumentationUrlBytes() { - java.lang.Object ref = documentationUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - documentationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CAPABILITIES_FIELD_NUMBER = 7; - private io.a2a.grpc.AgentCapabilities capabilities_; - /** - *
-   * A2A Capability set supported by the agent.
-   * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the capabilities field is set. - */ - @java.lang.Override - public boolean hasCapabilities() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-   * A2A Capability set supported by the agent.
-   * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - * @return The capabilities. - */ - @java.lang.Override - public io.a2a.grpc.AgentCapabilities getCapabilities() { - return capabilities_ == null ? io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; - } - /** - *
-   * A2A Capability set supported by the agent.
-   * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() { - return capabilities_ == null ? io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; - } - - public static final int SECURITY_SCHEMES_FIELD_NUMBER = 8; - private static final class SecuritySchemesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, io.a2a.grpc.SecurityScheme> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_SecuritySchemesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.MESSAGE, - io.a2a.grpc.SecurityScheme.getDefaultInstance()); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, io.a2a.grpc.SecurityScheme> securitySchemes_; - private com.google.protobuf.MapField - internalGetSecuritySchemes() { - if (securitySchemes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - SecuritySchemesDefaultEntryHolder.defaultEntry); - } - return securitySchemes_; - } - public int getSecuritySchemesCount() { - return internalGetSecuritySchemes().getMap().size(); - } - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public boolean containsSecuritySchemes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetSecuritySchemes().getMap().containsKey(key); - } - /** - * Use {@link #getSecuritySchemesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getSecuritySchemes() { - return getSecuritySchemesMap(); - } - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public java.util.Map getSecuritySchemesMap() { - return internalGetSecuritySchemes().getMap(); - } - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public /* nullable */ -io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault( - java.lang.String key, - /* nullable */ -io.a2a.grpc.SecurityScheme defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetSecuritySchemes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetSecuritySchemes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 13; - @SuppressWarnings("serial") - private java.util.List securityRequirements_; - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - @java.lang.Override - public java.util.List getSecurityRequirementsList() { - return securityRequirements_; - } - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - @java.lang.Override - public java.util.List - getSecurityRequirementsOrBuilderList() { - return securityRequirements_; - } - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - @java.lang.Override - public int getSecurityRequirementsCount() { - return securityRequirements_.size(); - } - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - @java.lang.Override - public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { - return securityRequirements_.get(index); - } - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - @java.lang.Override - public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( - int index) { - return securityRequirements_.get(index); - } - - public static final int DEFAULT_INPUT_MODES_FIELD_NUMBER = 10; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList defaultInputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the defaultInputModes. - */ - public com.google.protobuf.ProtocolStringList - getDefaultInputModesList() { - return defaultInputModes_; - } - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of defaultInputModes. - */ - public int getDefaultInputModesCount() { - return defaultInputModes_.size(); - } - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The defaultInputModes at the given index. - */ - public java.lang.String getDefaultInputModes(int index) { - return defaultInputModes_.get(index); - } - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the defaultInputModes at the given index. - */ - public com.google.protobuf.ByteString - getDefaultInputModesBytes(int index) { - return defaultInputModes_.getByteString(index); - } - - public static final int DEFAULT_OUTPUT_MODES_FIELD_NUMBER = 11; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList defaultOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the defaultOutputModes. - */ - public com.google.protobuf.ProtocolStringList - getDefaultOutputModesList() { - return defaultOutputModes_; - } - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of defaultOutputModes. - */ - public int getDefaultOutputModesCount() { - return defaultOutputModes_.size(); - } - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The defaultOutputModes at the given index. - */ - public java.lang.String getDefaultOutputModes(int index) { - return defaultOutputModes_.get(index); - } - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the defaultOutputModes at the given index. - */ - public com.google.protobuf.ByteString - getDefaultOutputModesBytes(int index) { - return defaultOutputModes_.getByteString(index); - } - - public static final int SKILLS_FIELD_NUMBER = 12; - @SuppressWarnings("serial") - private java.util.List skills_; - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List getSkillsList() { - return skills_; - } - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List - getSkillsOrBuilderList() { - return skills_; - } - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public int getSkillsCount() { - return skills_.size(); - } - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.AgentSkill getSkills(int index) { - return skills_.get(index); - } - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( - int index) { - return skills_.get(index); - } - - public static final int SIGNATURES_FIELD_NUMBER = 17; - @SuppressWarnings("serial") - private java.util.List signatures_; - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - @java.lang.Override - public java.util.List getSignaturesList() { - return signatures_; - } - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - @java.lang.Override - public java.util.List - getSignaturesOrBuilderList() { - return signatures_; - } - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - @java.lang.Override - public int getSignaturesCount() { - return signatures_.size(); - } - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - @java.lang.Override - public io.a2a.grpc.AgentCardSignature getSignatures(int index) { - return signatures_.get(index); - } - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - @java.lang.Override - public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( - int index) { - return signatures_.get(index); - } - - public static final int ICON_URL_FIELD_NUMBER = 18; - @SuppressWarnings("serial") - private volatile java.lang.Object iconUrl_ = ""; - /** - *
-   * An optional URL to an icon for the agent.
-   * 
- * - * optional string icon_url = 18; - * @return Whether the iconUrl field is set. - */ - @java.lang.Override - public boolean hasIconUrl() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-   * An optional URL to an icon for the agent.
-   * 
- * - * optional string icon_url = 18; - * @return The iconUrl. - */ - @java.lang.Override - public java.lang.String getIconUrl() { - java.lang.Object ref = iconUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - iconUrl_ = s; - return s; - } - } - /** - *
-   * An optional URL to an icon for the agent.
-   * 
- * - * optional string icon_url = 18; - * @return The bytes for iconUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIconUrlBytes() { - java.lang.Object ref = iconUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - iconUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, description_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(4, getProvider()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 5, version_); - } - if (((bitField0_ & 0x00000002) != 0)) { - com.google.protobuf.GeneratedMessage.writeString(output, 6, documentationUrl_); - } - if (((bitField0_ & 0x00000004) != 0)) { - output.writeMessage(7, getCapabilities()); - } - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetSecuritySchemes(), - SecuritySchemesDefaultEntryHolder.defaultEntry, - 8); - for (int i = 0; i < defaultInputModes_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 10, defaultInputModes_.getRaw(i)); - } - for (int i = 0; i < defaultOutputModes_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 11, defaultOutputModes_.getRaw(i)); - } - for (int i = 0; i < skills_.size(); i++) { - output.writeMessage(12, skills_.get(i)); - } - for (int i = 0; i < securityRequirements_.size(); i++) { - output.writeMessage(13, securityRequirements_.get(i)); - } - for (int i = 0; i < signatures_.size(); i++) { - output.writeMessage(17, signatures_.get(i)); - } - if (((bitField0_ & 0x00000008) != 0)) { - com.google.protobuf.GeneratedMessage.writeString(output, 18, iconUrl_); - } - for (int i = 0; i < supportedInterfaces_.size(); i++) { - output.writeMessage(19, supportedInterfaces_.get(i)); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, getProvider()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(5, version_); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(6, documentationUrl_); - } - if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(7, getCapabilities()); - } - for (java.util.Map.Entry entry - : internalGetSecuritySchemes().getMap().entrySet()) { - com.google.protobuf.MapEntry - securitySchemes__ = SecuritySchemesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(8, securitySchemes__); - } - { - int dataSize = 0; - for (int i = 0; i < defaultInputModes_.size(); i++) { - dataSize += computeStringSizeNoTag(defaultInputModes_.getRaw(i)); - } - size += dataSize; - size += 1 * getDefaultInputModesList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < defaultOutputModes_.size(); i++) { - dataSize += computeStringSizeNoTag(defaultOutputModes_.getRaw(i)); - } - size += dataSize; - size += 1 * getDefaultOutputModesList().size(); - } - for (int i = 0; i < skills_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(12, skills_.get(i)); - } - for (int i = 0; i < securityRequirements_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(13, securityRequirements_.get(i)); - } - for (int i = 0; i < signatures_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(17, signatures_.get(i)); - } - if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(18, iconUrl_); - } - for (int i = 0; i < supportedInterfaces_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(19, supportedInterfaces_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AgentCard)) { - return super.equals(obj); - } - io.a2a.grpc.AgentCard other = (io.a2a.grpc.AgentCard) obj; - - if (!getName() - .equals(other.getName())) return false; - if (!getDescription() - .equals(other.getDescription())) return false; - if (!getSupportedInterfacesList() - .equals(other.getSupportedInterfacesList())) return false; - if (hasProvider() != other.hasProvider()) return false; - if (hasProvider()) { - if (!getProvider() - .equals(other.getProvider())) return false; - } - if (!getVersion() - .equals(other.getVersion())) return false; - if (hasDocumentationUrl() != other.hasDocumentationUrl()) return false; - if (hasDocumentationUrl()) { - if (!getDocumentationUrl() - .equals(other.getDocumentationUrl())) return false; - } - if (hasCapabilities() != other.hasCapabilities()) return false; - if (hasCapabilities()) { - if (!getCapabilities() - .equals(other.getCapabilities())) return false; - } - if (!internalGetSecuritySchemes().equals( - other.internalGetSecuritySchemes())) return false; - if (!getSecurityRequirementsList() - .equals(other.getSecurityRequirementsList())) return false; - if (!getDefaultInputModesList() - .equals(other.getDefaultInputModesList())) return false; - if (!getDefaultOutputModesList() - .equals(other.getDefaultOutputModesList())) return false; - if (!getSkillsList() - .equals(other.getSkillsList())) return false; - if (!getSignaturesList() - .equals(other.getSignaturesList())) return false; - if (hasIconUrl() != other.hasIconUrl()) return false; - if (hasIconUrl()) { - if (!getIconUrl() - .equals(other.getIconUrl())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - if (getSupportedInterfacesCount() > 0) { - hash = (37 * hash) + SUPPORTED_INTERFACES_FIELD_NUMBER; - hash = (53 * hash) + getSupportedInterfacesList().hashCode(); - } - if (hasProvider()) { - hash = (37 * hash) + PROVIDER_FIELD_NUMBER; - hash = (53 * hash) + getProvider().hashCode(); - } - hash = (37 * hash) + VERSION_FIELD_NUMBER; - hash = (53 * hash) + getVersion().hashCode(); - if (hasDocumentationUrl()) { - hash = (37 * hash) + DOCUMENTATION_URL_FIELD_NUMBER; - hash = (53 * hash) + getDocumentationUrl().hashCode(); - } - if (hasCapabilities()) { - hash = (37 * hash) + CAPABILITIES_FIELD_NUMBER; - hash = (53 * hash) + getCapabilities().hashCode(); - } - if (!internalGetSecuritySchemes().getMap().isEmpty()) { - hash = (37 * hash) + SECURITY_SCHEMES_FIELD_NUMBER; - hash = (53 * hash) + internalGetSecuritySchemes().hashCode(); - } - if (getSecurityRequirementsCount() > 0) { - hash = (37 * hash) + SECURITY_REQUIREMENTS_FIELD_NUMBER; - hash = (53 * hash) + getSecurityRequirementsList().hashCode(); - } - if (getDefaultInputModesCount() > 0) { - hash = (37 * hash) + DEFAULT_INPUT_MODES_FIELD_NUMBER; - hash = (53 * hash) + getDefaultInputModesList().hashCode(); - } - if (getDefaultOutputModesCount() > 0) { - hash = (37 * hash) + DEFAULT_OUTPUT_MODES_FIELD_NUMBER; - hash = (53 * hash) + getDefaultOutputModesList().hashCode(); - } - if (getSkillsCount() > 0) { - hash = (37 * hash) + SKILLS_FIELD_NUMBER; - hash = (53 * hash) + getSkillsList().hashCode(); - } - if (getSignaturesCount() > 0) { - hash = (37 * hash) + SIGNATURES_FIELD_NUMBER; - hash = (53 * hash) + getSignaturesList().hashCode(); - } - if (hasIconUrl()) { - hash = (37 * hash) + ICON_URL_FIELD_NUMBER; - hash = (53 * hash) + getIconUrl().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AgentCard parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCard parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCard parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCard parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCard parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCard parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCard parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentCard parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AgentCard parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AgentCard parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AgentCard parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentCard parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AgentCard prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AgentCard]
-   * AgentCard is a self-describing manifest for an agent. It provides essential
-   * metadata including the agent's identity, capabilities, skills, supported
-   * communication methods, and security requirements.
-   * Next ID: 20
-   * 
- * - * Protobuf type {@code a2a.v1.AgentCard} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCard) - io.a2a.grpc.AgentCardOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 8: - return internalGetSecuritySchemes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 8: - return internalGetMutableSecuritySchemes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentCard.class, io.a2a.grpc.AgentCard.Builder.class); - } - - // Construct using io.a2a.grpc.AgentCard.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetSupportedInterfacesFieldBuilder(); - internalGetProviderFieldBuilder(); - internalGetCapabilitiesFieldBuilder(); - internalGetSecurityRequirementsFieldBuilder(); - internalGetSkillsFieldBuilder(); - internalGetSignaturesFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - name_ = ""; - description_ = ""; - if (supportedInterfacesBuilder_ == null) { - supportedInterfaces_ = java.util.Collections.emptyList(); - } else { - supportedInterfaces_ = null; - supportedInterfacesBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000004); - provider_ = null; - if (providerBuilder_ != null) { - providerBuilder_.dispose(); - providerBuilder_ = null; - } - version_ = ""; - documentationUrl_ = ""; - capabilities_ = null; - if (capabilitiesBuilder_ != null) { - capabilitiesBuilder_.dispose(); - capabilitiesBuilder_ = null; - } - internalGetMutableSecuritySchemes().clear(); - if (securityRequirementsBuilder_ == null) { - securityRequirements_ = java.util.Collections.emptyList(); - } else { - securityRequirements_ = null; - securityRequirementsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000100); - defaultInputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - defaultOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - if (skillsBuilder_ == null) { - skills_ = java.util.Collections.emptyList(); - } else { - skills_ = null; - skillsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000800); - if (signaturesBuilder_ == null) { - signatures_ = java.util.Collections.emptyList(); - } else { - signatures_ = null; - signaturesBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00001000); - iconUrl_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCard_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AgentCard getDefaultInstanceForType() { - return io.a2a.grpc.AgentCard.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AgentCard build() { - io.a2a.grpc.AgentCard result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AgentCard buildPartial() { - io.a2a.grpc.AgentCard result = new io.a2a.grpc.AgentCard(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.AgentCard result) { - if (supportedInterfacesBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0)) { - supportedInterfaces_ = java.util.Collections.unmodifiableList(supportedInterfaces_); - bitField0_ = (bitField0_ & ~0x00000004); - } - result.supportedInterfaces_ = supportedInterfaces_; - } else { - result.supportedInterfaces_ = supportedInterfacesBuilder_.build(); - } - if (securityRequirementsBuilder_ == null) { - if (((bitField0_ & 0x00000100) != 0)) { - securityRequirements_ = java.util.Collections.unmodifiableList(securityRequirements_); - bitField0_ = (bitField0_ & ~0x00000100); - } - result.securityRequirements_ = securityRequirements_; - } else { - result.securityRequirements_ = securityRequirementsBuilder_.build(); - } - if (skillsBuilder_ == null) { - if (((bitField0_ & 0x00000800) != 0)) { - skills_ = java.util.Collections.unmodifiableList(skills_); - bitField0_ = (bitField0_ & ~0x00000800); - } - result.skills_ = skills_; - } else { - result.skills_ = skillsBuilder_.build(); - } - if (signaturesBuilder_ == null) { - if (((bitField0_ & 0x00001000) != 0)) { - signatures_ = java.util.Collections.unmodifiableList(signatures_); - bitField0_ = (bitField0_ & ~0x00001000); - } - result.signatures_ = signatures_; - } else { - result.signatures_ = signaturesBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.AgentCard result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.name_ = name_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.description_ = description_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { - result.provider_ = providerBuilder_ == null - ? provider_ - : providerBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000010) != 0)) { - result.version_ = version_; - } - if (((from_bitField0_ & 0x00000020) != 0)) { - result.documentationUrl_ = documentationUrl_; - to_bitField0_ |= 0x00000002; - } - if (((from_bitField0_ & 0x00000040) != 0)) { - result.capabilities_ = capabilitiesBuilder_ == null - ? capabilities_ - : capabilitiesBuilder_.build(); - to_bitField0_ |= 0x00000004; - } - if (((from_bitField0_ & 0x00000080) != 0)) { - result.securitySchemes_ = internalGetSecuritySchemes().build(SecuritySchemesDefaultEntryHolder.defaultEntry); - } - if (((from_bitField0_ & 0x00000200) != 0)) { - defaultInputModes_.makeImmutable(); - result.defaultInputModes_ = defaultInputModes_; - } - if (((from_bitField0_ & 0x00000400) != 0)) { - defaultOutputModes_.makeImmutable(); - result.defaultOutputModes_ = defaultOutputModes_; - } - if (((from_bitField0_ & 0x00002000) != 0)) { - result.iconUrl_ = iconUrl_; - to_bitField0_ |= 0x00000008; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AgentCard) { - return mergeFrom((io.a2a.grpc.AgentCard)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AgentCard other) { - if (other == io.a2a.grpc.AgentCard.getDefaultInstance()) return this; - if (!other.getName().isEmpty()) { - name_ = other.name_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (supportedInterfacesBuilder_ == null) { - if (!other.supportedInterfaces_.isEmpty()) { - if (supportedInterfaces_.isEmpty()) { - supportedInterfaces_ = other.supportedInterfaces_; - bitField0_ = (bitField0_ & ~0x00000004); - } else { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.addAll(other.supportedInterfaces_); - } - onChanged(); - } - } else { - if (!other.supportedInterfaces_.isEmpty()) { - if (supportedInterfacesBuilder_.isEmpty()) { - supportedInterfacesBuilder_.dispose(); - supportedInterfacesBuilder_ = null; - supportedInterfaces_ = other.supportedInterfaces_; - bitField0_ = (bitField0_ & ~0x00000004); - supportedInterfacesBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetSupportedInterfacesFieldBuilder() : null; - } else { - supportedInterfacesBuilder_.addAllMessages(other.supportedInterfaces_); - } - } - } - if (other.hasProvider()) { - mergeProvider(other.getProvider()); - } - if (!other.getVersion().isEmpty()) { - version_ = other.version_; - bitField0_ |= 0x00000010; - onChanged(); - } - if (other.hasDocumentationUrl()) { - documentationUrl_ = other.documentationUrl_; - bitField0_ |= 0x00000020; - onChanged(); - } - if (other.hasCapabilities()) { - mergeCapabilities(other.getCapabilities()); - } - internalGetMutableSecuritySchemes().mergeFrom( - other.internalGetSecuritySchemes()); - bitField0_ |= 0x00000080; - if (securityRequirementsBuilder_ == null) { - if (!other.securityRequirements_.isEmpty()) { - if (securityRequirements_.isEmpty()) { - securityRequirements_ = other.securityRequirements_; - bitField0_ = (bitField0_ & ~0x00000100); - } else { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.addAll(other.securityRequirements_); - } - onChanged(); - } - } else { - if (!other.securityRequirements_.isEmpty()) { - if (securityRequirementsBuilder_.isEmpty()) { - securityRequirementsBuilder_.dispose(); - securityRequirementsBuilder_ = null; - securityRequirements_ = other.securityRequirements_; - bitField0_ = (bitField0_ & ~0x00000100); - securityRequirementsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetSecurityRequirementsFieldBuilder() : null; - } else { - securityRequirementsBuilder_.addAllMessages(other.securityRequirements_); - } - } - } - if (!other.defaultInputModes_.isEmpty()) { - if (defaultInputModes_.isEmpty()) { - defaultInputModes_ = other.defaultInputModes_; - bitField0_ |= 0x00000200; - } else { - ensureDefaultInputModesIsMutable(); - defaultInputModes_.addAll(other.defaultInputModes_); - } - onChanged(); - } - if (!other.defaultOutputModes_.isEmpty()) { - if (defaultOutputModes_.isEmpty()) { - defaultOutputModes_ = other.defaultOutputModes_; - bitField0_ |= 0x00000400; - } else { - ensureDefaultOutputModesIsMutable(); - defaultOutputModes_.addAll(other.defaultOutputModes_); - } - onChanged(); - } - if (skillsBuilder_ == null) { - if (!other.skills_.isEmpty()) { - if (skills_.isEmpty()) { - skills_ = other.skills_; - bitField0_ = (bitField0_ & ~0x00000800); - } else { - ensureSkillsIsMutable(); - skills_.addAll(other.skills_); - } - onChanged(); - } - } else { - if (!other.skills_.isEmpty()) { - if (skillsBuilder_.isEmpty()) { - skillsBuilder_.dispose(); - skillsBuilder_ = null; - skills_ = other.skills_; - bitField0_ = (bitField0_ & ~0x00000800); - skillsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetSkillsFieldBuilder() : null; - } else { - skillsBuilder_.addAllMessages(other.skills_); - } - } - } - if (signaturesBuilder_ == null) { - if (!other.signatures_.isEmpty()) { - if (signatures_.isEmpty()) { - signatures_ = other.signatures_; - bitField0_ = (bitField0_ & ~0x00001000); - } else { - ensureSignaturesIsMutable(); - signatures_.addAll(other.signatures_); - } - onChanged(); - } - } else { - if (!other.signatures_.isEmpty()) { - if (signaturesBuilder_.isEmpty()) { - signaturesBuilder_.dispose(); - signaturesBuilder_ = null; - signatures_ = other.signatures_; - bitField0_ = (bitField0_ & ~0x00001000); - signaturesBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetSignaturesFieldBuilder() : null; - } else { - signaturesBuilder_.addAllMessages(other.signatures_); - } - } - } - if (other.hasIconUrl()) { - iconUrl_ = other.iconUrl_; - bitField0_ |= 0x00002000; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 34: { - input.readMessage( - internalGetProviderFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 34 - case 42: { - version_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000010; - break; - } // case 42 - case 50: { - documentationUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000020; - break; - } // case 50 - case 58: { - input.readMessage( - internalGetCapabilitiesFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000040; - break; - } // case 58 - case 66: { - com.google.protobuf.MapEntry - securitySchemes__ = input.readMessage( - SecuritySchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableSecuritySchemes().ensureBuilderMap().put( - securitySchemes__.getKey(), securitySchemes__.getValue()); - bitField0_ |= 0x00000080; - break; - } // case 66 - case 82: { - java.lang.String s = input.readStringRequireUtf8(); - ensureDefaultInputModesIsMutable(); - defaultInputModes_.add(s); - break; - } // case 82 - case 90: { - java.lang.String s = input.readStringRequireUtf8(); - ensureDefaultOutputModesIsMutable(); - defaultOutputModes_.add(s); - break; - } // case 90 - case 98: { - io.a2a.grpc.AgentSkill m = - input.readMessage( - io.a2a.grpc.AgentSkill.parser(), - extensionRegistry); - if (skillsBuilder_ == null) { - ensureSkillsIsMutable(); - skills_.add(m); - } else { - skillsBuilder_.addMessage(m); - } - break; - } // case 98 - case 106: { - io.a2a.grpc.SecurityRequirement m = - input.readMessage( - io.a2a.grpc.SecurityRequirement.parser(), - extensionRegistry); - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(m); - } else { - securityRequirementsBuilder_.addMessage(m); - } - break; - } // case 106 - case 138: { - io.a2a.grpc.AgentCardSignature m = - input.readMessage( - io.a2a.grpc.AgentCardSignature.parser(), - extensionRegistry); - if (signaturesBuilder_ == null) { - ensureSignaturesIsMutable(); - signatures_.add(m); - } else { - signaturesBuilder_.addMessage(m); - } - break; - } // case 138 - case 146: { - iconUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00002000; - break; - } // case 146 - case 154: { - io.a2a.grpc.AgentInterface m = - input.readMessage( - io.a2a.grpc.AgentInterface.parser(), - extensionRegistry); - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(m); - } else { - supportedInterfacesBuilder_.addMessage(m); - } - break; - } // case 154 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object name_ = ""; - /** - *
-     * A human readable name for the agent.
-     * Example: "Recipe Agent"
-     * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A human readable name for the agent.
-     * Example: "Recipe Agent"
-     * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A human readable name for the agent.
-     * Example: "Recipe Agent"
-     * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The name to set. - * @return This builder for chaining. - */ - public Builder setName( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - name_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * A human readable name for the agent.
-     * Example: "Recipe Agent"
-     * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * A human readable name for the agent.
-     * Example: "Recipe Agent"
-     * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for name to set. - * @return This builder for chaining. - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - name_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object description_ = ""; - /** - *
-     * A human-readable description of the agent, assisting users and other agents
-     * in understanding its purpose.
-     * Example: "Agent that helps users with recipes and cooking."
-     * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A human-readable description of the agent, assisting users and other agents
-     * in understanding its purpose.
-     * Example: "Agent that helps users with recipes and cooking."
-     * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A human-readable description of the agent, assisting users and other agents
-     * in understanding its purpose.
-     * Example: "Agent that helps users with recipes and cooking."
-     * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * A human-readable description of the agent, assisting users and other agents
-     * in understanding its purpose.
-     * Example: "Agent that helps users with recipes and cooking."
-     * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * A human-readable description of the agent, assisting users and other agents
-     * in understanding its purpose.
-     * Example: "Agent that helps users with recipes and cooking."
-     * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.util.List supportedInterfaces_ = - java.util.Collections.emptyList(); - private void ensureSupportedInterfacesIsMutable() { - if (!((bitField0_ & 0x00000004) != 0)) { - supportedInterfaces_ = new java.util.ArrayList(supportedInterfaces_); - bitField0_ |= 0x00000004; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> supportedInterfacesBuilder_; - - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List getSupportedInterfacesList() { - if (supportedInterfacesBuilder_ == null) { - return java.util.Collections.unmodifiableList(supportedInterfaces_); - } else { - return supportedInterfacesBuilder_.getMessageList(); - } - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public int getSupportedInterfacesCount() { - if (supportedInterfacesBuilder_ == null) { - return supportedInterfaces_.size(); - } else { - return supportedInterfacesBuilder_.getCount(); - } - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentInterface getSupportedInterfaces(int index) { - if (supportedInterfacesBuilder_ == null) { - return supportedInterfaces_.get(index); - } else { - return supportedInterfacesBuilder_.getMessage(index); - } - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface value) { - if (supportedInterfacesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.set(index, value); - onChanged(); - } else { - supportedInterfacesBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.set(index, builderForValue.build()); - onChanged(); - } else { - supportedInterfacesBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSupportedInterfaces(io.a2a.grpc.AgentInterface value) { - if (supportedInterfacesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(value); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface value) { - if (supportedInterfacesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(index, value); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSupportedInterfaces( - io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(builderForValue.build()); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSupportedInterfaces( - int index, io.a2a.grpc.AgentInterface.Builder builderForValue) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.add(index, builderForValue.build()); - onChanged(); - } else { - supportedInterfacesBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addAllSupportedInterfaces( - java.lang.Iterable values) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, supportedInterfaces_); - onChanged(); - } else { - supportedInterfacesBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearSupportedInterfaces() { - if (supportedInterfacesBuilder_ == null) { - supportedInterfaces_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - } else { - supportedInterfacesBuilder_.clear(); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeSupportedInterfaces(int index) { - if (supportedInterfacesBuilder_ == null) { - ensureSupportedInterfacesIsMutable(); - supportedInterfaces_.remove(index); - onChanged(); - } else { - supportedInterfacesBuilder_.remove(index); - } - return this; - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentInterface.Builder getSupportedInterfacesBuilder( - int index) { - return internalGetSupportedInterfacesFieldBuilder().getBuilder(index); - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( - int index) { - if (supportedInterfacesBuilder_ == null) { - return supportedInterfaces_.get(index); } else { - return supportedInterfacesBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getSupportedInterfacesOrBuilderList() { - if (supportedInterfacesBuilder_ != null) { - return supportedInterfacesBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(supportedInterfaces_); - } - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder() { - return internalGetSupportedInterfacesFieldBuilder().addBuilder( - io.a2a.grpc.AgentInterface.getDefaultInstance()); - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentInterface.Builder addSupportedInterfacesBuilder( - int index) { - return internalGetSupportedInterfacesFieldBuilder().addBuilder( - index, io.a2a.grpc.AgentInterface.getDefaultInstance()); - } - /** - *
-     * Ordered list of supported interfaces. First entry is preferred.
-     * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getSupportedInterfacesBuilderList() { - return internalGetSupportedInterfacesFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder> - internalGetSupportedInterfacesFieldBuilder() { - if (supportedInterfacesBuilder_ == null) { - supportedInterfacesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentInterface, io.a2a.grpc.AgentInterface.Builder, io.a2a.grpc.AgentInterfaceOrBuilder>( - supportedInterfaces_, - ((bitField0_ & 0x00000004) != 0), - getParentForChildren(), - isClean()); - supportedInterfaces_ = null; - } - return supportedInterfacesBuilder_; - } - - private io.a2a.grpc.AgentProvider provider_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AgentProvider, io.a2a.grpc.AgentProvider.Builder, io.a2a.grpc.AgentProviderOrBuilder> providerBuilder_; - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - * @return Whether the provider field is set. - */ - public boolean hasProvider() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - * @return The provider. - */ - public io.a2a.grpc.AgentProvider getProvider() { - if (providerBuilder_ == null) { - return provider_ == null ? io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_; - } else { - return providerBuilder_.getMessage(); - } - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - public Builder setProvider(io.a2a.grpc.AgentProvider value) { - if (providerBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - provider_ = value; - } else { - providerBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - public Builder setProvider( - io.a2a.grpc.AgentProvider.Builder builderForValue) { - if (providerBuilder_ == null) { - provider_ = builderForValue.build(); - } else { - providerBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - public Builder mergeProvider(io.a2a.grpc.AgentProvider value) { - if (providerBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - provider_ != null && - provider_ != io.a2a.grpc.AgentProvider.getDefaultInstance()) { - getProviderBuilder().mergeFrom(value); - } else { - provider_ = value; - } - } else { - providerBuilder_.mergeFrom(value); - } - if (provider_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - public Builder clearProvider() { - bitField0_ = (bitField0_ & ~0x00000008); - provider_ = null; - if (providerBuilder_ != null) { - providerBuilder_.dispose(); - providerBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - public io.a2a.grpc.AgentProvider.Builder getProviderBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetProviderFieldBuilder().getBuilder(); - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - public io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder() { - if (providerBuilder_ != null) { - return providerBuilder_.getMessageOrBuilder(); - } else { - return provider_ == null ? - io.a2a.grpc.AgentProvider.getDefaultInstance() : provider_; - } - } - /** - *
-     * The service provider of the agent.
-     * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AgentProvider, io.a2a.grpc.AgentProvider.Builder, io.a2a.grpc.AgentProviderOrBuilder> - internalGetProviderFieldBuilder() { - if (providerBuilder_ == null) { - providerBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AgentProvider, io.a2a.grpc.AgentProvider.Builder, io.a2a.grpc.AgentProviderOrBuilder>( - getProvider(), - getParentForChildren(), - isClean()); - provider_ = null; - } - return providerBuilder_; - } - - private java.lang.Object version_ = ""; - /** - *
-     * The version of the agent.
-     * Example: "1.0.0"
-     * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The version. - */ - public java.lang.String getVersion() { - java.lang.Object ref = version_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - version_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The version of the agent.
-     * Example: "1.0.0"
-     * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for version. - */ - public com.google.protobuf.ByteString - getVersionBytes() { - java.lang.Object ref = version_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - version_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The version of the agent.
-     * Example: "1.0.0"
-     * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @param value The version to set. - * @return This builder for chaining. - */ - public Builder setVersion( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - version_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * The version of the agent.
-     * Example: "1.0.0"
-     * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearVersion() { - version_ = getDefaultInstance().getVersion(); - bitField0_ = (bitField0_ & ~0x00000010); - onChanged(); - return this; - } - /** - *
-     * The version of the agent.
-     * Example: "1.0.0"
-     * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for version to set. - * @return This builder for chaining. - */ - public Builder setVersionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - version_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - - private java.lang.Object documentationUrl_ = ""; - /** - *
-     * A url to provide additional documentation about the agent.
-     * 
- * - * optional string documentation_url = 6; - * @return Whether the documentationUrl field is set. - */ - public boolean hasDocumentationUrl() { - return ((bitField0_ & 0x00000020) != 0); - } - /** - *
-     * A url to provide additional documentation about the agent.
-     * 
- * - * optional string documentation_url = 6; - * @return The documentationUrl. - */ - public java.lang.String getDocumentationUrl() { - java.lang.Object ref = documentationUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - documentationUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A url to provide additional documentation about the agent.
-     * 
- * - * optional string documentation_url = 6; - * @return The bytes for documentationUrl. - */ - public com.google.protobuf.ByteString - getDocumentationUrlBytes() { - java.lang.Object ref = documentationUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - documentationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A url to provide additional documentation about the agent.
-     * 
- * - * optional string documentation_url = 6; - * @param value The documentationUrl to set. - * @return This builder for chaining. - */ - public Builder setDocumentationUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - documentationUrl_ = value; - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * A url to provide additional documentation about the agent.
-     * 
- * - * optional string documentation_url = 6; - * @return This builder for chaining. - */ - public Builder clearDocumentationUrl() { - documentationUrl_ = getDefaultInstance().getDocumentationUrl(); - bitField0_ = (bitField0_ & ~0x00000020); - onChanged(); - return this; - } - /** - *
-     * A url to provide additional documentation about the agent.
-     * 
- * - * optional string documentation_url = 6; - * @param value The bytes for documentationUrl to set. - * @return This builder for chaining. - */ - public Builder setDocumentationUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - documentationUrl_ = value; - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - - private io.a2a.grpc.AgentCapabilities capabilities_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AgentCapabilities, io.a2a.grpc.AgentCapabilities.Builder, io.a2a.grpc.AgentCapabilitiesOrBuilder> capabilitiesBuilder_; - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the capabilities field is set. - */ - public boolean hasCapabilities() { - return ((bitField0_ & 0x00000040) != 0); - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - * @return The capabilities. - */ - public io.a2a.grpc.AgentCapabilities getCapabilities() { - if (capabilitiesBuilder_ == null) { - return capabilities_ == null ? io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; - } else { - return capabilitiesBuilder_.getMessage(); - } - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setCapabilities(io.a2a.grpc.AgentCapabilities value) { - if (capabilitiesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - capabilities_ = value; - } else { - capabilitiesBuilder_.setMessage(value); - } - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setCapabilities( - io.a2a.grpc.AgentCapabilities.Builder builderForValue) { - if (capabilitiesBuilder_ == null) { - capabilities_ = builderForValue.build(); - } else { - capabilitiesBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeCapabilities(io.a2a.grpc.AgentCapabilities value) { - if (capabilitiesBuilder_ == null) { - if (((bitField0_ & 0x00000040) != 0) && - capabilities_ != null && - capabilities_ != io.a2a.grpc.AgentCapabilities.getDefaultInstance()) { - getCapabilitiesBuilder().mergeFrom(value); - } else { - capabilities_ = value; - } - } else { - capabilitiesBuilder_.mergeFrom(value); - } - if (capabilities_ != null) { - bitField0_ |= 0x00000040; - onChanged(); - } - return this; - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearCapabilities() { - bitField0_ = (bitField0_ & ~0x00000040); - capabilities_ = null; - if (capabilitiesBuilder_ != null) { - capabilitiesBuilder_.dispose(); - capabilitiesBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentCapabilities.Builder getCapabilitiesBuilder() { - bitField0_ |= 0x00000040; - onChanged(); - return internalGetCapabilitiesFieldBuilder().getBuilder(); - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder() { - if (capabilitiesBuilder_ != null) { - return capabilitiesBuilder_.getMessageOrBuilder(); - } else { - return capabilities_ == null ? - io.a2a.grpc.AgentCapabilities.getDefaultInstance() : capabilities_; - } - } - /** - *
-     * A2A Capability set supported by the agent.
-     * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AgentCapabilities, io.a2a.grpc.AgentCapabilities.Builder, io.a2a.grpc.AgentCapabilitiesOrBuilder> - internalGetCapabilitiesFieldBuilder() { - if (capabilitiesBuilder_ == null) { - capabilitiesBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AgentCapabilities, io.a2a.grpc.AgentCapabilities.Builder, io.a2a.grpc.AgentCapabilitiesOrBuilder>( - getCapabilities(), - getParentForChildren(), - isClean()); - capabilities_ = null; - } - return capabilitiesBuilder_; - } - - private static final class SecuritySchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter { - @java.lang.Override - public io.a2a.grpc.SecurityScheme build(io.a2a.grpc.SecuritySchemeOrBuilder val) { - if (val instanceof io.a2a.grpc.SecurityScheme) { return (io.a2a.grpc.SecurityScheme) val; } - return ((io.a2a.grpc.SecurityScheme.Builder) val).build(); - } - - @java.lang.Override - public com.google.protobuf.MapEntry defaultEntry() { - return SecuritySchemesDefaultEntryHolder.defaultEntry; - } - }; - private static final SecuritySchemesConverter securitySchemesConverter = new SecuritySchemesConverter(); - - private com.google.protobuf.MapFieldBuilder< - java.lang.String, io.a2a.grpc.SecuritySchemeOrBuilder, io.a2a.grpc.SecurityScheme, io.a2a.grpc.SecurityScheme.Builder> securitySchemes_; - private com.google.protobuf.MapFieldBuilder - internalGetSecuritySchemes() { - if (securitySchemes_ == null) { - return new com.google.protobuf.MapFieldBuilder<>(securitySchemesConverter); - } - return securitySchemes_; - } - private com.google.protobuf.MapFieldBuilder - internalGetMutableSecuritySchemes() { - if (securitySchemes_ == null) { - securitySchemes_ = new com.google.protobuf.MapFieldBuilder<>(securitySchemesConverter); - } - bitField0_ |= 0x00000080; - onChanged(); - return securitySchemes_; - } - public int getSecuritySchemesCount() { - return internalGetSecuritySchemes().ensureBuilderMap().size(); - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public boolean containsSecuritySchemes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetSecuritySchemes().ensureBuilderMap().containsKey(key); - } - /** - * Use {@link #getSecuritySchemesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getSecuritySchemes() { - return getSecuritySchemesMap(); - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public java.util.Map getSecuritySchemesMap() { - return internalGetSecuritySchemes().getImmutableMap(); - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public /* nullable */ -io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault( - java.lang.String key, - /* nullable */ -io.a2a.grpc.SecurityScheme defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap(); - return map.containsKey(key) ? securitySchemesConverter.build(map.get(key)) : defaultValue; - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - @java.lang.Override - public io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = internalGetMutableSecuritySchemes().ensureBuilderMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return securitySchemesConverter.build(map.get(key)); - } - public Builder clearSecuritySchemes() { - bitField0_ = (bitField0_ & ~0x00000080); - internalGetMutableSecuritySchemes().clear(); - return this; - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - public Builder removeSecuritySchemes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableSecuritySchemes().ensureBuilderMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableSecuritySchemes() { - bitField0_ |= 0x00000080; - return internalGetMutableSecuritySchemes().ensureMessageMap(); - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - public Builder putSecuritySchemes( - java.lang.String key, - io.a2a.grpc.SecurityScheme value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableSecuritySchemes().ensureBuilderMap() - .put(key, value); - bitField0_ |= 0x00000080; - return this; - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - public Builder putAllSecuritySchemes( - java.util.Map values) { - for (java.util.Map.Entry e : values.entrySet()) { - if (e.getKey() == null || e.getValue() == null) { - throw new NullPointerException(); - } - } - internalGetMutableSecuritySchemes().ensureBuilderMap() - .putAll(values); - bitField0_ |= 0x00000080; - return this; - } - /** - *
-     * The security scheme details used for authenticating with this agent.
-     * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - public io.a2a.grpc.SecurityScheme.Builder putSecuritySchemesBuilderIfAbsent( - java.lang.String key) { - java.util.Map builderMap = internalGetMutableSecuritySchemes().ensureBuilderMap(); - io.a2a.grpc.SecuritySchemeOrBuilder entry = builderMap.get(key); - if (entry == null) { - entry = io.a2a.grpc.SecurityScheme.newBuilder(); - builderMap.put(key, entry); - } - if (entry instanceof io.a2a.grpc.SecurityScheme) { - entry = ((io.a2a.grpc.SecurityScheme) entry).toBuilder(); - builderMap.put(key, entry); - } - return (io.a2a.grpc.SecurityScheme.Builder) entry; - } - - private java.util.List securityRequirements_ = - java.util.Collections.emptyList(); - private void ensureSecurityRequirementsIsMutable() { - if (!((bitField0_ & 0x00000100) != 0)) { - securityRequirements_ = new java.util.ArrayList(securityRequirements_); - bitField0_ |= 0x00000100; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_; - - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public java.util.List getSecurityRequirementsList() { - if (securityRequirementsBuilder_ == null) { - return java.util.Collections.unmodifiableList(securityRequirements_); - } else { - return securityRequirementsBuilder_.getMessageList(); - } - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public int getSecurityRequirementsCount() { - if (securityRequirementsBuilder_ == null) { - return securityRequirements_.size(); - } else { - return securityRequirementsBuilder_.getCount(); - } - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { - if (securityRequirementsBuilder_ == null) { - return securityRequirements_.get(index); - } else { - return securityRequirementsBuilder_.getMessage(index); - } - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder setSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement value) { - if (securityRequirementsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSecurityRequirementsIsMutable(); - securityRequirements_.set(index, value); - onChanged(); - } else { - securityRequirementsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder setSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.set(index, builderForValue.build()); - onChanged(); - } else { - securityRequirementsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { - if (securityRequirementsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(value); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder addSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement value) { - if (securityRequirementsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(index, value); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder addSecurityRequirements( - io.a2a.grpc.SecurityRequirement.Builder builderForValue) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(builderForValue.build()); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder addSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(index, builderForValue.build()); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder addAllSecurityRequirements( - java.lang.Iterable values) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, securityRequirements_); - onChanged(); - } else { - securityRequirementsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder clearSecurityRequirements() { - if (securityRequirementsBuilder_ == null) { - securityRequirements_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000100); - onChanged(); - } else { - securityRequirementsBuilder_.clear(); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public Builder removeSecurityRequirements(int index) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.remove(index); - onChanged(); - } else { - securityRequirementsBuilder_.remove(index); - } - return this; - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( - int index) { - return internalGetSecurityRequirementsFieldBuilder().getBuilder(index); - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( - int index) { - if (securityRequirementsBuilder_ == null) { - return securityRequirements_.get(index); } else { - return securityRequirementsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public java.util.List - getSecurityRequirementsOrBuilderList() { - if (securityRequirementsBuilder_ != null) { - return securityRequirementsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(securityRequirements_); - } - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() { - return internalGetSecurityRequirementsFieldBuilder().addBuilder( - io.a2a.grpc.SecurityRequirement.getDefaultInstance()); - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( - int index) { - return internalGetSecurityRequirementsFieldBuilder().addBuilder( - index, io.a2a.grpc.SecurityRequirement.getDefaultInstance()); - } - /** - *
-     * Security requirements for contacting the agent.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - public java.util.List - getSecurityRequirementsBuilderList() { - return internalGetSecurityRequirementsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> - internalGetSecurityRequirementsFieldBuilder() { - if (securityRequirementsBuilder_ == null) { - securityRequirementsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder>( - securityRequirements_, - ((bitField0_ & 0x00000100) != 0), - getParentForChildren(), - isClean()); - securityRequirements_ = null; - } - return securityRequirementsBuilder_; - } - - private com.google.protobuf.LazyStringArrayList defaultInputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureDefaultInputModesIsMutable() { - if (!defaultInputModes_.isModifiable()) { - defaultInputModes_ = new com.google.protobuf.LazyStringArrayList(defaultInputModes_); - } - bitField0_ |= 0x00000200; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the defaultInputModes. - */ - public com.google.protobuf.ProtocolStringList - getDefaultInputModesList() { - defaultInputModes_.makeImmutable(); - return defaultInputModes_; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of defaultInputModes. - */ - public int getDefaultInputModesCount() { - return defaultInputModes_.size(); - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The defaultInputModes at the given index. - */ - public java.lang.String getDefaultInputModes(int index) { - return defaultInputModes_.get(index); - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the defaultInputModes at the given index. - */ - public com.google.protobuf.ByteString - getDefaultInputModesBytes(int index) { - return defaultInputModes_.getByteString(index); - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index to set the value at. - * @param value The defaultInputModes to set. - * @return This builder for chaining. - */ - public Builder setDefaultInputModes( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureDefaultInputModesIsMutable(); - defaultInputModes_.set(index, value); - bitField0_ |= 0x00000200; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param value The defaultInputModes to add. - * @return This builder for chaining. - */ - public Builder addDefaultInputModes( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureDefaultInputModesIsMutable(); - defaultInputModes_.add(value); - bitField0_ |= 0x00000200; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param values The defaultInputModes to add. - * @return This builder for chaining. - */ - public Builder addAllDefaultInputModes( - java.lang.Iterable values) { - ensureDefaultInputModesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, defaultInputModes_); - bitField0_ |= 0x00000200; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearDefaultInputModes() { - defaultInputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000200);; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * The set of interaction modes that the agent supports across all skills.
-     * This can be overridden per skill. Defined as media types.
-     * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes of the defaultInputModes to add. - * @return This builder for chaining. - */ - public Builder addDefaultInputModesBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureDefaultInputModesIsMutable(); - defaultInputModes_.add(value); - bitField0_ |= 0x00000200; - onChanged(); - return this; - } - - private com.google.protobuf.LazyStringArrayList defaultOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureDefaultOutputModesIsMutable() { - if (!defaultOutputModes_.isModifiable()) { - defaultOutputModes_ = new com.google.protobuf.LazyStringArrayList(defaultOutputModes_); - } - bitField0_ |= 0x00000400; - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the defaultOutputModes. - */ - public com.google.protobuf.ProtocolStringList - getDefaultOutputModesList() { - defaultOutputModes_.makeImmutable(); - return defaultOutputModes_; - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of defaultOutputModes. - */ - public int getDefaultOutputModesCount() { - return defaultOutputModes_.size(); - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The defaultOutputModes at the given index. - */ - public java.lang.String getDefaultOutputModes(int index) { - return defaultOutputModes_.get(index); - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the defaultOutputModes at the given index. - */ - public com.google.protobuf.ByteString - getDefaultOutputModesBytes(int index) { - return defaultOutputModes_.getByteString(index); - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index to set the value at. - * @param value The defaultOutputModes to set. - * @return This builder for chaining. - */ - public Builder setDefaultOutputModes( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureDefaultOutputModesIsMutable(); - defaultOutputModes_.set(index, value); - bitField0_ |= 0x00000400; - onChanged(); - return this; - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param value The defaultOutputModes to add. - * @return This builder for chaining. - */ - public Builder addDefaultOutputModes( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureDefaultOutputModesIsMutable(); - defaultOutputModes_.add(value); - bitField0_ |= 0x00000400; - onChanged(); - return this; - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param values The defaultOutputModes to add. - * @return This builder for chaining. - */ - public Builder addAllDefaultOutputModes( - java.lang.Iterable values) { - ensureDefaultOutputModesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, defaultOutputModes_); - bitField0_ |= 0x00000400; - onChanged(); - return this; - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearDefaultOutputModes() { - defaultOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000400);; - onChanged(); - return this; - } - /** - *
-     * The media types supported as outputs from this agent.
-     * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes of the defaultOutputModes to add. - * @return This builder for chaining. - */ - public Builder addDefaultOutputModesBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureDefaultOutputModesIsMutable(); - defaultOutputModes_.add(value); - bitField0_ |= 0x00000400; - onChanged(); - return this; - } - - private java.util.List skills_ = - java.util.Collections.emptyList(); - private void ensureSkillsIsMutable() { - if (!((bitField0_ & 0x00000800) != 0)) { - skills_ = new java.util.ArrayList(skills_); - bitField0_ |= 0x00000800; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder> skillsBuilder_; - - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List getSkillsList() { - if (skillsBuilder_ == null) { - return java.util.Collections.unmodifiableList(skills_); - } else { - return skillsBuilder_.getMessageList(); - } - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public int getSkillsCount() { - if (skillsBuilder_ == null) { - return skills_.size(); - } else { - return skillsBuilder_.getCount(); - } - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentSkill getSkills(int index) { - if (skillsBuilder_ == null) { - return skills_.get(index); - } else { - return skillsBuilder_.getMessage(index); - } - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setSkills( - int index, io.a2a.grpc.AgentSkill value) { - if (skillsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSkillsIsMutable(); - skills_.set(index, value); - onChanged(); - } else { - skillsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setSkills( - int index, io.a2a.grpc.AgentSkill.Builder builderForValue) { - if (skillsBuilder_ == null) { - ensureSkillsIsMutable(); - skills_.set(index, builderForValue.build()); - onChanged(); - } else { - skillsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSkills(io.a2a.grpc.AgentSkill value) { - if (skillsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSkillsIsMutable(); - skills_.add(value); - onChanged(); - } else { - skillsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSkills( - int index, io.a2a.grpc.AgentSkill value) { - if (skillsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSkillsIsMutable(); - skills_.add(index, value); - onChanged(); - } else { - skillsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSkills( - io.a2a.grpc.AgentSkill.Builder builderForValue) { - if (skillsBuilder_ == null) { - ensureSkillsIsMutable(); - skills_.add(builderForValue.build()); - onChanged(); - } else { - skillsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addSkills( - int index, io.a2a.grpc.AgentSkill.Builder builderForValue) { - if (skillsBuilder_ == null) { - ensureSkillsIsMutable(); - skills_.add(index, builderForValue.build()); - onChanged(); - } else { - skillsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addAllSkills( - java.lang.Iterable values) { - if (skillsBuilder_ == null) { - ensureSkillsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, skills_); - onChanged(); - } else { - skillsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearSkills() { - if (skillsBuilder_ == null) { - skills_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000800); - onChanged(); - } else { - skillsBuilder_.clear(); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeSkills(int index) { - if (skillsBuilder_ == null) { - ensureSkillsIsMutable(); - skills_.remove(index); - onChanged(); - } else { - skillsBuilder_.remove(index); - } - return this; - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentSkill.Builder getSkillsBuilder( - int index) { - return internalGetSkillsFieldBuilder().getBuilder(index); - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( - int index) { - if (skillsBuilder_ == null) { - return skills_.get(index); } else { - return skillsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getSkillsOrBuilderList() { - if (skillsBuilder_ != null) { - return skillsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(skills_); - } - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder() { - return internalGetSkillsFieldBuilder().addBuilder( - io.a2a.grpc.AgentSkill.getDefaultInstance()); - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.AgentSkill.Builder addSkillsBuilder( - int index) { - return internalGetSkillsFieldBuilder().addBuilder( - index, io.a2a.grpc.AgentSkill.getDefaultInstance()); - } - /** - *
-     * Skills represent an ability of an agent. It is largely
-     * a descriptive concept but represents a more focused set of behaviors that the
-     * agent is likely to succeed at.
-     * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getSkillsBuilderList() { - return internalGetSkillsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder> - internalGetSkillsFieldBuilder() { - if (skillsBuilder_ == null) { - skillsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentSkill, io.a2a.grpc.AgentSkill.Builder, io.a2a.grpc.AgentSkillOrBuilder>( - skills_, - ((bitField0_ & 0x00000800) != 0), - getParentForChildren(), - isClean()); - skills_ = null; - } - return skillsBuilder_; - } - - private java.util.List signatures_ = - java.util.Collections.emptyList(); - private void ensureSignaturesIsMutable() { - if (!((bitField0_ & 0x00001000) != 0)) { - signatures_ = new java.util.ArrayList(signatures_); - bitField0_ |= 0x00001000; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder> signaturesBuilder_; - - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public java.util.List getSignaturesList() { - if (signaturesBuilder_ == null) { - return java.util.Collections.unmodifiableList(signatures_); - } else { - return signaturesBuilder_.getMessageList(); - } - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public int getSignaturesCount() { - if (signaturesBuilder_ == null) { - return signatures_.size(); - } else { - return signaturesBuilder_.getCount(); - } - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public io.a2a.grpc.AgentCardSignature getSignatures(int index) { - if (signaturesBuilder_ == null) { - return signatures_.get(index); - } else { - return signaturesBuilder_.getMessage(index); - } - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder setSignatures( - int index, io.a2a.grpc.AgentCardSignature value) { - if (signaturesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSignaturesIsMutable(); - signatures_.set(index, value); - onChanged(); - } else { - signaturesBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder setSignatures( - int index, io.a2a.grpc.AgentCardSignature.Builder builderForValue) { - if (signaturesBuilder_ == null) { - ensureSignaturesIsMutable(); - signatures_.set(index, builderForValue.build()); - onChanged(); - } else { - signaturesBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder addSignatures(io.a2a.grpc.AgentCardSignature value) { - if (signaturesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSignaturesIsMutable(); - signatures_.add(value); - onChanged(); - } else { - signaturesBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder addSignatures( - int index, io.a2a.grpc.AgentCardSignature value) { - if (signaturesBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSignaturesIsMutable(); - signatures_.add(index, value); - onChanged(); - } else { - signaturesBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder addSignatures( - io.a2a.grpc.AgentCardSignature.Builder builderForValue) { - if (signaturesBuilder_ == null) { - ensureSignaturesIsMutable(); - signatures_.add(builderForValue.build()); - onChanged(); - } else { - signaturesBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder addSignatures( - int index, io.a2a.grpc.AgentCardSignature.Builder builderForValue) { - if (signaturesBuilder_ == null) { - ensureSignaturesIsMutable(); - signatures_.add(index, builderForValue.build()); - onChanged(); - } else { - signaturesBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder addAllSignatures( - java.lang.Iterable values) { - if (signaturesBuilder_ == null) { - ensureSignaturesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, signatures_); - onChanged(); - } else { - signaturesBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder clearSignatures() { - if (signaturesBuilder_ == null) { - signatures_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00001000); - onChanged(); - } else { - signaturesBuilder_.clear(); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public Builder removeSignatures(int index) { - if (signaturesBuilder_ == null) { - ensureSignaturesIsMutable(); - signatures_.remove(index); - onChanged(); - } else { - signaturesBuilder_.remove(index); - } - return this; - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public io.a2a.grpc.AgentCardSignature.Builder getSignaturesBuilder( - int index) { - return internalGetSignaturesFieldBuilder().getBuilder(index); - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( - int index) { - if (signaturesBuilder_ == null) { - return signatures_.get(index); } else { - return signaturesBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public java.util.List - getSignaturesOrBuilderList() { - if (signaturesBuilder_ != null) { - return signaturesBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(signatures_); - } - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder() { - return internalGetSignaturesFieldBuilder().addBuilder( - io.a2a.grpc.AgentCardSignature.getDefaultInstance()); - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public io.a2a.grpc.AgentCardSignature.Builder addSignaturesBuilder( - int index) { - return internalGetSignaturesFieldBuilder().addBuilder( - index, io.a2a.grpc.AgentCardSignature.getDefaultInstance()); - } - /** - *
-     * JSON Web Signatures computed for this AgentCard.
-     * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - public java.util.List - getSignaturesBuilderList() { - return internalGetSignaturesFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder> - internalGetSignaturesFieldBuilder() { - if (signaturesBuilder_ == null) { - signaturesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.AgentCardSignature, io.a2a.grpc.AgentCardSignature.Builder, io.a2a.grpc.AgentCardSignatureOrBuilder>( - signatures_, - ((bitField0_ & 0x00001000) != 0), - getParentForChildren(), - isClean()); - signatures_ = null; - } - return signaturesBuilder_; - } - - private java.lang.Object iconUrl_ = ""; - /** - *
-     * An optional URL to an icon for the agent.
-     * 
- * - * optional string icon_url = 18; - * @return Whether the iconUrl field is set. - */ - public boolean hasIconUrl() { - return ((bitField0_ & 0x00002000) != 0); - } - /** - *
-     * An optional URL to an icon for the agent.
-     * 
- * - * optional string icon_url = 18; - * @return The iconUrl. - */ - public java.lang.String getIconUrl() { - java.lang.Object ref = iconUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - iconUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * An optional URL to an icon for the agent.
-     * 
- * - * optional string icon_url = 18; - * @return The bytes for iconUrl. - */ - public com.google.protobuf.ByteString - getIconUrlBytes() { - java.lang.Object ref = iconUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - iconUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * An optional URL to an icon for the agent.
-     * 
- * - * optional string icon_url = 18; - * @param value The iconUrl to set. - * @return This builder for chaining. - */ - public Builder setIconUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - iconUrl_ = value; - bitField0_ |= 0x00002000; - onChanged(); - return this; - } - /** - *
-     * An optional URL to an icon for the agent.
-     * 
- * - * optional string icon_url = 18; - * @return This builder for chaining. - */ - public Builder clearIconUrl() { - iconUrl_ = getDefaultInstance().getIconUrl(); - bitField0_ = (bitField0_ & ~0x00002000); - onChanged(); - return this; - } - /** - *
-     * An optional URL to an icon for the agent.
-     * 
- * - * optional string icon_url = 18; - * @param value The bytes for iconUrl to set. - * @return This builder for chaining. - */ - public Builder setIconUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - iconUrl_ = value; - bitField0_ |= 0x00002000; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCard) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AgentCard) - private static final io.a2a.grpc.AgentCard DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AgentCard(); - } - - public static io.a2a.grpc.AgentCard getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AgentCard parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AgentCard getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java deleted file mode 100644 index 379ec0282..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardOrBuilder.java +++ /dev/null @@ -1,522 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AgentCardOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCard) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * A human readable name for the agent.
-   * Example: "Recipe Agent"
-   * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - java.lang.String getName(); - /** - *
-   * A human readable name for the agent.
-   * Example: "Recipe Agent"
-   * 
- * - * string name = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - com.google.protobuf.ByteString - getNameBytes(); - - /** - *
-   * A human-readable description of the agent, assisting users and other agents
-   * in understanding its purpose.
-   * Example: "Agent that helps users with recipes and cooking."
-   * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * A human-readable description of the agent, assisting users and other agents
-   * in understanding its purpose.
-   * Example: "Agent that helps users with recipes and cooking."
-   * 
- * - * string description = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getSupportedInterfacesList(); - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.AgentInterface getSupportedInterfaces(int index); - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - int getSupportedInterfacesCount(); - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getSupportedInterfacesOrBuilderList(); - /** - *
-   * Ordered list of supported interfaces. First entry is preferred.
-   * 
- * - * repeated .a2a.v1.AgentInterface supported_interfaces = 19 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.AgentInterfaceOrBuilder getSupportedInterfacesOrBuilder( - int index); - - /** - *
-   * The service provider of the agent.
-   * 
- * - * .a2a.v1.AgentProvider provider = 4; - * @return Whether the provider field is set. - */ - boolean hasProvider(); - /** - *
-   * The service provider of the agent.
-   * 
- * - * .a2a.v1.AgentProvider provider = 4; - * @return The provider. - */ - io.a2a.grpc.AgentProvider getProvider(); - /** - *
-   * The service provider of the agent.
-   * 
- * - * .a2a.v1.AgentProvider provider = 4; - */ - io.a2a.grpc.AgentProviderOrBuilder getProviderOrBuilder(); - - /** - *
-   * The version of the agent.
-   * Example: "1.0.0"
-   * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The version. - */ - java.lang.String getVersion(); - /** - *
-   * The version of the agent.
-   * Example: "1.0.0"
-   * 
- * - * string version = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for version. - */ - com.google.protobuf.ByteString - getVersionBytes(); - - /** - *
-   * A url to provide additional documentation about the agent.
-   * 
- * - * optional string documentation_url = 6; - * @return Whether the documentationUrl field is set. - */ - boolean hasDocumentationUrl(); - /** - *
-   * A url to provide additional documentation about the agent.
-   * 
- * - * optional string documentation_url = 6; - * @return The documentationUrl. - */ - java.lang.String getDocumentationUrl(); - /** - *
-   * A url to provide additional documentation about the agent.
-   * 
- * - * optional string documentation_url = 6; - * @return The bytes for documentationUrl. - */ - com.google.protobuf.ByteString - getDocumentationUrlBytes(); - - /** - *
-   * A2A Capability set supported by the agent.
-   * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the capabilities field is set. - */ - boolean hasCapabilities(); - /** - *
-   * A2A Capability set supported by the agent.
-   * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - * @return The capabilities. - */ - io.a2a.grpc.AgentCapabilities getCapabilities(); - /** - *
-   * A2A Capability set supported by the agent.
-   * 
- * - * .a2a.v1.AgentCapabilities capabilities = 7 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.AgentCapabilitiesOrBuilder getCapabilitiesOrBuilder(); - - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - int getSecuritySchemesCount(); - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - boolean containsSecuritySchemes( - java.lang.String key); - /** - * Use {@link #getSecuritySchemesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getSecuritySchemes(); - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - java.util.Map - getSecuritySchemesMap(); - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - /* nullable */ -io.a2a.grpc.SecurityScheme getSecuritySchemesOrDefault( - java.lang.String key, - /* nullable */ -io.a2a.grpc.SecurityScheme defaultValue); - /** - *
-   * The security scheme details used for authenticating with this agent.
-   * 
- * - * map<string, .a2a.v1.SecurityScheme> security_schemes = 8; - */ - io.a2a.grpc.SecurityScheme getSecuritySchemesOrThrow( - java.lang.String key); - - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - java.util.List - getSecurityRequirementsList(); - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index); - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - int getSecurityRequirementsCount(); - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - java.util.List - getSecurityRequirementsOrBuilderList(); - /** - *
-   * Security requirements for contacting the agent.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 13; - */ - io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( - int index); - - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the defaultInputModes. - */ - java.util.List - getDefaultInputModesList(); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of defaultInputModes. - */ - int getDefaultInputModesCount(); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The defaultInputModes at the given index. - */ - java.lang.String getDefaultInputModes(int index); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * The set of interaction modes that the agent supports across all skills.
-   * This can be overridden per skill. Defined as media types.
-   * 
- * - * repeated string default_input_modes = 10 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the defaultInputModes at the given index. - */ - com.google.protobuf.ByteString - getDefaultInputModesBytes(int index); - - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the defaultOutputModes. - */ - java.util.List - getDefaultOutputModesList(); - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of defaultOutputModes. - */ - int getDefaultOutputModesCount(); - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The defaultOutputModes at the given index. - */ - java.lang.String getDefaultOutputModes(int index); - /** - *
-   * The media types supported as outputs from this agent.
-   * 
- * - * repeated string default_output_modes = 11 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the defaultOutputModes at the given index. - */ - com.google.protobuf.ByteString - getDefaultOutputModesBytes(int index); - - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getSkillsList(); - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.AgentSkill getSkills(int index); - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - int getSkillsCount(); - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getSkillsOrBuilderList(); - /** - *
-   * Skills represent an ability of an agent. It is largely
-   * a descriptive concept but represents a more focused set of behaviors that the
-   * agent is likely to succeed at.
-   * 
- * - * repeated .a2a.v1.AgentSkill skills = 12 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.AgentSkillOrBuilder getSkillsOrBuilder( - int index); - - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - java.util.List - getSignaturesList(); - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - io.a2a.grpc.AgentCardSignature getSignatures(int index); - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - int getSignaturesCount(); - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - java.util.List - getSignaturesOrBuilderList(); - /** - *
-   * JSON Web Signatures computed for this AgentCard.
-   * 
- * - * repeated .a2a.v1.AgentCardSignature signatures = 17; - */ - io.a2a.grpc.AgentCardSignatureOrBuilder getSignaturesOrBuilder( - int index); - - /** - *
-   * An optional URL to an icon for the agent.
-   * 
- * - * optional string icon_url = 18; - * @return Whether the iconUrl field is set. - */ - boolean hasIconUrl(); - /** - *
-   * An optional URL to an icon for the agent.
-   * 
- * - * optional string icon_url = 18; - * @return The iconUrl. - */ - java.lang.String getIconUrl(); - /** - *
-   * An optional URL to an icon for the agent.
-   * 
- * - * optional string icon_url = 18; - * @return The bytes for iconUrl. - */ - com.google.protobuf.ByteString - getIconUrlBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java deleted file mode 100644 index eef107309..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignature.java +++ /dev/null @@ -1,954 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AgentCardSignature]
- * AgentCardSignature represents a JWS signature of an AgentCard.
- * This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
- * 
- * - * Protobuf type {@code a2a.v1.AgentCardSignature} - */ -@com.google.protobuf.Generated -public final class AgentCardSignature extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentCardSignature) - AgentCardSignatureOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AgentCardSignature"); - } - // Use AgentCardSignature.newBuilder() to construct. - private AgentCardSignature(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AgentCardSignature() { - protected_ = ""; - signature_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentCardSignature.class, io.a2a.grpc.AgentCardSignature.Builder.class); - } - - private int bitField0_; - public static final int PROTECTED_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object protected_ = ""; - /** - *
-   * The protected JWS header for the signature. This is always a
-   * base64url-encoded JSON object. Required.
-   * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The protected. - */ - @java.lang.Override - public java.lang.String getProtected() { - java.lang.Object ref = protected_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protected_ = s; - return s; - } - } - /** - *
-   * The protected JWS header for the signature. This is always a
-   * base64url-encoded JSON object. Required.
-   * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protected. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getProtectedBytes() { - java.lang.Object ref = protected_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protected_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SIGNATURE_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object signature_ = ""; - /** - *
-   * The computed signature, base64url-encoded. Required.
-   * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The signature. - */ - @java.lang.Override - public java.lang.String getSignature() { - java.lang.Object ref = signature_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - signature_ = s; - return s; - } - } - /** - *
-   * The computed signature, base64url-encoded. Required.
-   * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for signature. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getSignatureBytes() { - java.lang.Object ref = signature_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - signature_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int HEADER_FIELD_NUMBER = 3; - private com.google.protobuf.Struct header_; - /** - *
-   * The unprotected JWS header values.
-   * 
- * - * .google.protobuf.Struct header = 3; - * @return Whether the header field is set. - */ - @java.lang.Override - public boolean hasHeader() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The unprotected JWS header values.
-   * 
- * - * .google.protobuf.Struct header = 3; - * @return The header. - */ - @java.lang.Override - public com.google.protobuf.Struct getHeader() { - return header_ == null ? com.google.protobuf.Struct.getDefaultInstance() : header_; - } - /** - *
-   * The unprotected JWS header values.
-   * 
- * - * .google.protobuf.Struct header = 3; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getHeaderOrBuilder() { - return header_ == null ? com.google.protobuf.Struct.getDefaultInstance() : header_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protected_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, protected_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(signature_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, signature_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(3, getHeader()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protected_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, protected_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(signature_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, signature_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getHeader()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AgentCardSignature)) { - return super.equals(obj); - } - io.a2a.grpc.AgentCardSignature other = (io.a2a.grpc.AgentCardSignature) obj; - - if (!getProtected() - .equals(other.getProtected())) return false; - if (!getSignature() - .equals(other.getSignature())) return false; - if (hasHeader() != other.hasHeader()) return false; - if (hasHeader()) { - if (!getHeader() - .equals(other.getHeader())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + PROTECTED_FIELD_NUMBER; - hash = (53 * hash) + getProtected().hashCode(); - hash = (37 * hash) + SIGNATURE_FIELD_NUMBER; - hash = (53 * hash) + getSignature().hashCode(); - if (hasHeader()) { - hash = (37 * hash) + HEADER_FIELD_NUMBER; - hash = (53 * hash) + getHeader().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AgentCardSignature parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCardSignature parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCardSignature parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCardSignature parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCardSignature parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentCardSignature parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentCardSignature parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentCardSignature parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AgentCardSignature parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AgentCardSignature parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AgentCardSignature parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentCardSignature parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AgentCardSignature prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AgentCardSignature]
-   * AgentCardSignature represents a JWS signature of an AgentCard.
-   * This follows the JSON format of an RFC 7515 JSON Web Signature (JWS).
-   * 
- * - * Protobuf type {@code a2a.v1.AgentCardSignature} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentCardSignature) - io.a2a.grpc.AgentCardSignatureOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentCardSignature.class, io.a2a.grpc.AgentCardSignature.Builder.class); - } - - // Construct using io.a2a.grpc.AgentCardSignature.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetHeaderFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - protected_ = ""; - signature_ = ""; - header_ = null; - if (headerBuilder_ != null) { - headerBuilder_.dispose(); - headerBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentCardSignature_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AgentCardSignature getDefaultInstanceForType() { - return io.a2a.grpc.AgentCardSignature.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AgentCardSignature build() { - io.a2a.grpc.AgentCardSignature result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AgentCardSignature buildPartial() { - io.a2a.grpc.AgentCardSignature result = new io.a2a.grpc.AgentCardSignature(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.AgentCardSignature result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.protected_ = protected_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.signature_ = signature_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.header_ = headerBuilder_ == null - ? header_ - : headerBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AgentCardSignature) { - return mergeFrom((io.a2a.grpc.AgentCardSignature)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AgentCardSignature other) { - if (other == io.a2a.grpc.AgentCardSignature.getDefaultInstance()) return this; - if (!other.getProtected().isEmpty()) { - protected_ = other.protected_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getSignature().isEmpty()) { - signature_ = other.signature_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.hasHeader()) { - mergeHeader(other.getHeader()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - protected_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - signature_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetHeaderFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object protected_ = ""; - /** - *
-     * The protected JWS header for the signature. This is always a
-     * base64url-encoded JSON object. Required.
-     * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The protected. - */ - public java.lang.String getProtected() { - java.lang.Object ref = protected_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protected_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The protected JWS header for the signature. This is always a
-     * base64url-encoded JSON object. Required.
-     * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protected. - */ - public com.google.protobuf.ByteString - getProtectedBytes() { - java.lang.Object ref = protected_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protected_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The protected JWS header for the signature. This is always a
-     * base64url-encoded JSON object. Required.
-     * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The protected to set. - * @return This builder for chaining. - */ - public Builder setProtected( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - protected_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The protected JWS header for the signature. This is always a
-     * base64url-encoded JSON object. Required.
-     * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearProtected() { - protected_ = getDefaultInstance().getProtected(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The protected JWS header for the signature. This is always a
-     * base64url-encoded JSON object. Required.
-     * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for protected to set. - * @return This builder for chaining. - */ - public Builder setProtectedBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - protected_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object signature_ = ""; - /** - *
-     * The computed signature, base64url-encoded. Required.
-     * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The signature. - */ - public java.lang.String getSignature() { - java.lang.Object ref = signature_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - signature_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The computed signature, base64url-encoded. Required.
-     * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for signature. - */ - public com.google.protobuf.ByteString - getSignatureBytes() { - java.lang.Object ref = signature_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - signature_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The computed signature, base64url-encoded. Required.
-     * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The signature to set. - * @return This builder for chaining. - */ - public Builder setSignature( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - signature_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The computed signature, base64url-encoded. Required.
-     * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearSignature() { - signature_ = getDefaultInstance().getSignature(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The computed signature, base64url-encoded. Required.
-     * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for signature to set. - * @return This builder for chaining. - */ - public Builder setSignatureBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - signature_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private com.google.protobuf.Struct header_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> headerBuilder_; - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - * @return Whether the header field is set. - */ - public boolean hasHeader() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - * @return The header. - */ - public com.google.protobuf.Struct getHeader() { - if (headerBuilder_ == null) { - return header_ == null ? com.google.protobuf.Struct.getDefaultInstance() : header_; - } else { - return headerBuilder_.getMessage(); - } - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - */ - public Builder setHeader(com.google.protobuf.Struct value) { - if (headerBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - header_ = value; - } else { - headerBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - */ - public Builder setHeader( - com.google.protobuf.Struct.Builder builderForValue) { - if (headerBuilder_ == null) { - header_ = builderForValue.build(); - } else { - headerBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - */ - public Builder mergeHeader(com.google.protobuf.Struct value) { - if (headerBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - header_ != null && - header_ != com.google.protobuf.Struct.getDefaultInstance()) { - getHeaderBuilder().mergeFrom(value); - } else { - header_ = value; - } - } else { - headerBuilder_.mergeFrom(value); - } - if (header_ != null) { - bitField0_ |= 0x00000004; - onChanged(); - } - return this; - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - */ - public Builder clearHeader() { - bitField0_ = (bitField0_ & ~0x00000004); - header_ = null; - if (headerBuilder_ != null) { - headerBuilder_.dispose(); - headerBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - */ - public com.google.protobuf.Struct.Builder getHeaderBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return internalGetHeaderFieldBuilder().getBuilder(); - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - */ - public com.google.protobuf.StructOrBuilder getHeaderOrBuilder() { - if (headerBuilder_ != null) { - return headerBuilder_.getMessageOrBuilder(); - } else { - return header_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : header_; - } - } - /** - *
-     * The unprotected JWS header values.
-     * 
- * - * .google.protobuf.Struct header = 3; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetHeaderFieldBuilder() { - if (headerBuilder_ == null) { - headerBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getHeader(), - getParentForChildren(), - isClean()); - header_ = null; - } - return headerBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentCardSignature) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AgentCardSignature) - private static final io.a2a.grpc.AgentCardSignature DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AgentCardSignature(); - } - - public static io.a2a.grpc.AgentCardSignature getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AgentCardSignature parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AgentCardSignature getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java deleted file mode 100644 index 1d05b9c6d..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentCardSignatureOrBuilder.java +++ /dev/null @@ -1,81 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AgentCardSignatureOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentCardSignature) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The protected JWS header for the signature. This is always a
-   * base64url-encoded JSON object. Required.
-   * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The protected. - */ - java.lang.String getProtected(); - /** - *
-   * The protected JWS header for the signature. This is always a
-   * base64url-encoded JSON object. Required.
-   * 
- * - * string protected = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protected. - */ - com.google.protobuf.ByteString - getProtectedBytes(); - - /** - *
-   * The computed signature, base64url-encoded. Required.
-   * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The signature. - */ - java.lang.String getSignature(); - /** - *
-   * The computed signature, base64url-encoded. Required.
-   * 
- * - * string signature = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for signature. - */ - com.google.protobuf.ByteString - getSignatureBytes(); - - /** - *
-   * The unprotected JWS header values.
-   * 
- * - * .google.protobuf.Struct header = 3; - * @return Whether the header field is set. - */ - boolean hasHeader(); - /** - *
-   * The unprotected JWS header values.
-   * 
- * - * .google.protobuf.Struct header = 3; - * @return The header. - */ - com.google.protobuf.Struct getHeader(); - /** - *
-   * The unprotected JWS header values.
-   * 
- * - * .google.protobuf.Struct header = 3; - */ - com.google.protobuf.StructOrBuilder getHeaderOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java deleted file mode 100644 index 6f942268e..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtension.java +++ /dev/null @@ -1,1028 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AgentExtension]
- * A declaration of a protocol extension supported by an Agent.
- * 
- * - * Protobuf type {@code a2a.v1.AgentExtension} - */ -@com.google.protobuf.Generated -public final class AgentExtension extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentExtension) - AgentExtensionOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AgentExtension"); - } - // Use AgentExtension.newBuilder() to construct. - private AgentExtension(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AgentExtension() { - uri_ = ""; - description_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentExtension.class, io.a2a.grpc.AgentExtension.Builder.class); - } - - private int bitField0_; - public static final int URI_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object uri_ = ""; - /** - *
-   * The unique URI identifying the extension.
-   * 
- * - * string uri = 1; - * @return The uri. - */ - @java.lang.Override - public java.lang.String getUri() { - java.lang.Object ref = uri_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - uri_ = s; - return s; - } - } - /** - *
-   * The unique URI identifying the extension.
-   * 
- * - * string uri = 1; - * @return The bytes for uri. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getUriBytes() { - java.lang.Object ref = uri_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - uri_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int DESCRIPTION_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * A human-readable description of how this agent uses the extension.
-   * 
- * - * string description = 2; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * A human-readable description of how this agent uses the extension.
-   * 
- * - * string description = 2; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int REQUIRED_FIELD_NUMBER = 3; - private boolean required_ = false; - /** - *
-   * If true, the client must understand and comply with the extension's requirements.
-   * 
- * - * bool required = 3; - * @return The required. - */ - @java.lang.Override - public boolean getRequired() { - return required_; - } - - public static final int PARAMS_FIELD_NUMBER = 4; - private com.google.protobuf.Struct params_; - /** - *
-   * Optional, extension-specific configuration parameters.
-   * 
- * - * .google.protobuf.Struct params = 4; - * @return Whether the params field is set. - */ - @java.lang.Override - public boolean hasParams() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * Optional, extension-specific configuration parameters.
-   * 
- * - * .google.protobuf.Struct params = 4; - * @return The params. - */ - @java.lang.Override - public com.google.protobuf.Struct getParams() { - return params_ == null ? com.google.protobuf.Struct.getDefaultInstance() : params_; - } - /** - *
-   * Optional, extension-specific configuration parameters.
-   * 
- * - * .google.protobuf.Struct params = 4; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getParamsOrBuilder() { - return params_ == null ? com.google.protobuf.Struct.getDefaultInstance() : params_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(uri_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, uri_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, description_); - } - if (required_ != false) { - output.writeBool(3, required_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(4, getParams()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(uri_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, uri_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_); - } - if (required_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(3, required_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, getParams()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AgentExtension)) { - return super.equals(obj); - } - io.a2a.grpc.AgentExtension other = (io.a2a.grpc.AgentExtension) obj; - - if (!getUri() - .equals(other.getUri())) return false; - if (!getDescription() - .equals(other.getDescription())) return false; - if (getRequired() - != other.getRequired()) return false; - if (hasParams() != other.hasParams()) return false; - if (hasParams()) { - if (!getParams() - .equals(other.getParams())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + URI_FIELD_NUMBER; - hash = (53 * hash) + getUri().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - hash = (37 * hash) + REQUIRED_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getRequired()); - if (hasParams()) { - hash = (37 * hash) + PARAMS_FIELD_NUMBER; - hash = (53 * hash) + getParams().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AgentExtension parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentExtension parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentExtension parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentExtension parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentExtension parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentExtension parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentExtension parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentExtension parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AgentExtension parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AgentExtension parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AgentExtension parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentExtension parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AgentExtension prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AgentExtension]
-   * A declaration of a protocol extension supported by an Agent.
-   * 
- * - * Protobuf type {@code a2a.v1.AgentExtension} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentExtension) - io.a2a.grpc.AgentExtensionOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentExtension.class, io.a2a.grpc.AgentExtension.Builder.class); - } - - // Construct using io.a2a.grpc.AgentExtension.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetParamsFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - uri_ = ""; - description_ = ""; - required_ = false; - params_ = null; - if (paramsBuilder_ != null) { - paramsBuilder_.dispose(); - paramsBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentExtension_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AgentExtension getDefaultInstanceForType() { - return io.a2a.grpc.AgentExtension.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AgentExtension build() { - io.a2a.grpc.AgentExtension result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AgentExtension buildPartial() { - io.a2a.grpc.AgentExtension result = new io.a2a.grpc.AgentExtension(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.AgentExtension result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.uri_ = uri_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.description_ = description_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.required_ = required_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { - result.params_ = paramsBuilder_ == null - ? params_ - : paramsBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AgentExtension) { - return mergeFrom((io.a2a.grpc.AgentExtension)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AgentExtension other) { - if (other == io.a2a.grpc.AgentExtension.getDefaultInstance()) return this; - if (!other.getUri().isEmpty()) { - uri_ = other.uri_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.getRequired() != false) { - setRequired(other.getRequired()); - } - if (other.hasParams()) { - mergeParams(other.getParams()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - uri_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 24: { - required_ = input.readBool(); - bitField0_ |= 0x00000004; - break; - } // case 24 - case 34: { - input.readMessage( - internalGetParamsFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object uri_ = ""; - /** - *
-     * The unique URI identifying the extension.
-     * 
- * - * string uri = 1; - * @return The uri. - */ - public java.lang.String getUri() { - java.lang.Object ref = uri_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - uri_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The unique URI identifying the extension.
-     * 
- * - * string uri = 1; - * @return The bytes for uri. - */ - public com.google.protobuf.ByteString - getUriBytes() { - java.lang.Object ref = uri_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - uri_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The unique URI identifying the extension.
-     * 
- * - * string uri = 1; - * @param value The uri to set. - * @return This builder for chaining. - */ - public Builder setUri( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - uri_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The unique URI identifying the extension.
-     * 
- * - * string uri = 1; - * @return This builder for chaining. - */ - public Builder clearUri() { - uri_ = getDefaultInstance().getUri(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The unique URI identifying the extension.
-     * 
- * - * string uri = 1; - * @param value The bytes for uri to set. - * @return This builder for chaining. - */ - public Builder setUriBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - uri_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object description_ = ""; - /** - *
-     * A human-readable description of how this agent uses the extension.
-     * 
- * - * string description = 2; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A human-readable description of how this agent uses the extension.
-     * 
- * - * string description = 2; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A human-readable description of how this agent uses the extension.
-     * 
- * - * string description = 2; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * A human-readable description of how this agent uses the extension.
-     * 
- * - * string description = 2; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * A human-readable description of how this agent uses the extension.
-     * 
- * - * string description = 2; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private boolean required_ ; - /** - *
-     * If true, the client must understand and comply with the extension's requirements.
-     * 
- * - * bool required = 3; - * @return The required. - */ - @java.lang.Override - public boolean getRequired() { - return required_; - } - /** - *
-     * If true, the client must understand and comply with the extension's requirements.
-     * 
- * - * bool required = 3; - * @param value The required to set. - * @return This builder for chaining. - */ - public Builder setRequired(boolean value) { - - required_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * If true, the client must understand and comply with the extension's requirements.
-     * 
- * - * bool required = 3; - * @return This builder for chaining. - */ - public Builder clearRequired() { - bitField0_ = (bitField0_ & ~0x00000004); - required_ = false; - onChanged(); - return this; - } - - private com.google.protobuf.Struct params_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> paramsBuilder_; - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - * @return Whether the params field is set. - */ - public boolean hasParams() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - * @return The params. - */ - public com.google.protobuf.Struct getParams() { - if (paramsBuilder_ == null) { - return params_ == null ? com.google.protobuf.Struct.getDefaultInstance() : params_; - } else { - return paramsBuilder_.getMessage(); - } - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - */ - public Builder setParams(com.google.protobuf.Struct value) { - if (paramsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - params_ = value; - } else { - paramsBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - */ - public Builder setParams( - com.google.protobuf.Struct.Builder builderForValue) { - if (paramsBuilder_ == null) { - params_ = builderForValue.build(); - } else { - paramsBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - */ - public Builder mergeParams(com.google.protobuf.Struct value) { - if (paramsBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - params_ != null && - params_ != com.google.protobuf.Struct.getDefaultInstance()) { - getParamsBuilder().mergeFrom(value); - } else { - params_ = value; - } - } else { - paramsBuilder_.mergeFrom(value); - } - if (params_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - */ - public Builder clearParams() { - bitField0_ = (bitField0_ & ~0x00000008); - params_ = null; - if (paramsBuilder_ != null) { - paramsBuilder_.dispose(); - paramsBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - */ - public com.google.protobuf.Struct.Builder getParamsBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetParamsFieldBuilder().getBuilder(); - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - */ - public com.google.protobuf.StructOrBuilder getParamsOrBuilder() { - if (paramsBuilder_ != null) { - return paramsBuilder_.getMessageOrBuilder(); - } else { - return params_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : params_; - } - } - /** - *
-     * Optional, extension-specific configuration parameters.
-     * 
- * - * .google.protobuf.Struct params = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetParamsFieldBuilder() { - if (paramsBuilder_ == null) { - paramsBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getParams(), - getParentForChildren(), - isClean()); - params_ = null; - } - return paramsBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentExtension) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AgentExtension) - private static final io.a2a.grpc.AgentExtension DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AgentExtension(); - } - - public static io.a2a.grpc.AgentExtension getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AgentExtension parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AgentExtension getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java deleted file mode 100644 index e5df98bb1..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentExtensionOrBuilder.java +++ /dev/null @@ -1,89 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AgentExtensionOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentExtension) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The unique URI identifying the extension.
-   * 
- * - * string uri = 1; - * @return The uri. - */ - java.lang.String getUri(); - /** - *
-   * The unique URI identifying the extension.
-   * 
- * - * string uri = 1; - * @return The bytes for uri. - */ - com.google.protobuf.ByteString - getUriBytes(); - - /** - *
-   * A human-readable description of how this agent uses the extension.
-   * 
- * - * string description = 2; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * A human-readable description of how this agent uses the extension.
-   * 
- * - * string description = 2; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * If true, the client must understand and comply with the extension's requirements.
-   * 
- * - * bool required = 3; - * @return The required. - */ - boolean getRequired(); - - /** - *
-   * Optional, extension-specific configuration parameters.
-   * 
- * - * .google.protobuf.Struct params = 4; - * @return Whether the params field is set. - */ - boolean hasParams(); - /** - *
-   * Optional, extension-specific configuration parameters.
-   * 
- * - * .google.protobuf.Struct params = 4; - * @return The params. - */ - com.google.protobuf.Struct getParams(); - /** - *
-   * Optional, extension-specific configuration parameters.
-   * 
- * - * .google.protobuf.Struct params = 4; - */ - com.google.protobuf.StructOrBuilder getParamsOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java deleted file mode 100644 index ac8001a8e..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterface.java +++ /dev/null @@ -1,1069 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AgentInterface]
- * Declares a combination of a target URL, transport and protocol version for interacting with the agent.
- * This allows agents to expose the same functionality over multiple protocol binding mechanisms.
- * 
- * - * Protobuf type {@code a2a.v1.AgentInterface} - */ -@com.google.protobuf.Generated -public final class AgentInterface extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentInterface) - AgentInterfaceOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AgentInterface"); - } - // Use AgentInterface.newBuilder() to construct. - private AgentInterface(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AgentInterface() { - url_ = ""; - protocolBinding_ = ""; - tenant_ = ""; - protocolVersion_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentInterface.class, io.a2a.grpc.AgentInterface.Builder.class); - } - - public static final int URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object url_ = ""; - /** - *
-   * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-   * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - @java.lang.Override - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } - } - /** - *
-   * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-   * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PROTOCOL_BINDING_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object protocolBinding_ = ""; - /** - *
-   * The protocol binding supported at this URL. This is an open form string, to be
-   * easily extended for other protocol bindings. The core ones officially
-   * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-   * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolBinding. - */ - @java.lang.Override - public java.lang.String getProtocolBinding() { - java.lang.Object ref = protocolBinding_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protocolBinding_ = s; - return s; - } - } - /** - *
-   * The protocol binding supported at this URL. This is an open form string, to be
-   * easily extended for other protocol bindings. The core ones officially
-   * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-   * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolBinding. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getProtocolBindingBytes() { - java.lang.Object ref = protocolBinding_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocolBinding_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TENANT_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Tenant to be set in the request when calling the agent.
-   * 
- * - * string tenant = 3; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Tenant to be set in the request when calling the agent.
-   * 
- * - * string tenant = 3; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PROTOCOL_VERSION_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object protocolVersion_ = ""; - /** - *
-   * The version of the A2A protocol this interface exposes.
-   * Use the latest supported minor version per major version.
-   * Examples: "0.3", "1.0"
-   * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolVersion. - */ - @java.lang.Override - public java.lang.String getProtocolVersion() { - java.lang.Object ref = protocolVersion_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protocolVersion_ = s; - return s; - } - } - /** - *
-   * The version of the A2A protocol this interface exposes.
-   * Use the latest supported minor version per major version.
-   * Examples: "0.3", "1.0"
-   * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolVersion. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getProtocolVersionBytes() { - java.lang.Object ref = protocolVersion_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocolVersion_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolBinding_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, protocolBinding_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolVersion_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, protocolVersion_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolBinding_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, protocolBinding_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(protocolVersion_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, protocolVersion_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AgentInterface)) { - return super.equals(obj); - } - io.a2a.grpc.AgentInterface other = (io.a2a.grpc.AgentInterface) obj; - - if (!getUrl() - .equals(other.getUrl())) return false; - if (!getProtocolBinding() - .equals(other.getProtocolBinding())) return false; - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getProtocolVersion() - .equals(other.getProtocolVersion())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + URL_FIELD_NUMBER; - hash = (53 * hash) + getUrl().hashCode(); - hash = (37 * hash) + PROTOCOL_BINDING_FIELD_NUMBER; - hash = (53 * hash) + getProtocolBinding().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + PROTOCOL_VERSION_FIELD_NUMBER; - hash = (53 * hash) + getProtocolVersion().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AgentInterface parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentInterface parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentInterface parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentInterface parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentInterface parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentInterface parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentInterface parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentInterface parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AgentInterface parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AgentInterface parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AgentInterface parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentInterface parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AgentInterface prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AgentInterface]
-   * Declares a combination of a target URL, transport and protocol version for interacting with the agent.
-   * This allows agents to expose the same functionality over multiple protocol binding mechanisms.
-   * 
- * - * Protobuf type {@code a2a.v1.AgentInterface} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentInterface) - io.a2a.grpc.AgentInterfaceOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentInterface.class, io.a2a.grpc.AgentInterface.Builder.class); - } - - // Construct using io.a2a.grpc.AgentInterface.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - url_ = ""; - protocolBinding_ = ""; - tenant_ = ""; - protocolVersion_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentInterface_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AgentInterface getDefaultInstanceForType() { - return io.a2a.grpc.AgentInterface.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AgentInterface build() { - io.a2a.grpc.AgentInterface result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AgentInterface buildPartial() { - io.a2a.grpc.AgentInterface result = new io.a2a.grpc.AgentInterface(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.AgentInterface result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.url_ = url_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.protocolBinding_ = protocolBinding_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.protocolVersion_ = protocolVersion_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AgentInterface) { - return mergeFrom((io.a2a.grpc.AgentInterface)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AgentInterface other) { - if (other == io.a2a.grpc.AgentInterface.getDefaultInstance()) return this; - if (!other.getUrl().isEmpty()) { - url_ = other.url_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getProtocolBinding().isEmpty()) { - protocolBinding_ = other.protocolBinding_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (!other.getProtocolVersion().isEmpty()) { - protocolVersion_ = other.protocolVersion_; - bitField0_ |= 0x00000008; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - url_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - protocolBinding_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - protocolVersion_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000008; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object url_ = ""; - /** - *
-     * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-     * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-     * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-     * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The url to set. - * @return This builder for chaining. - */ - public Builder setUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - url_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-     * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearUrl() { - url_ = getDefaultInstance().getUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-     * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for url to set. - * @return This builder for chaining. - */ - public Builder setUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - url_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object protocolBinding_ = ""; - /** - *
-     * The protocol binding supported at this URL. This is an open form string, to be
-     * easily extended for other protocol bindings. The core ones officially
-     * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-     * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolBinding. - */ - public java.lang.String getProtocolBinding() { - java.lang.Object ref = protocolBinding_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protocolBinding_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The protocol binding supported at this URL. This is an open form string, to be
-     * easily extended for other protocol bindings. The core ones officially
-     * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-     * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolBinding. - */ - public com.google.protobuf.ByteString - getProtocolBindingBytes() { - java.lang.Object ref = protocolBinding_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocolBinding_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The protocol binding supported at this URL. This is an open form string, to be
-     * easily extended for other protocol bindings. The core ones officially
-     * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-     * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The protocolBinding to set. - * @return This builder for chaining. - */ - public Builder setProtocolBinding( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - protocolBinding_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The protocol binding supported at this URL. This is an open form string, to be
-     * easily extended for other protocol bindings. The core ones officially
-     * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-     * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearProtocolBinding() { - protocolBinding_ = getDefaultInstance().getProtocolBinding(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The protocol binding supported at this URL. This is an open form string, to be
-     * easily extended for other protocol bindings. The core ones officially
-     * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-     * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for protocolBinding to set. - * @return This builder for chaining. - */ - public Builder setProtocolBindingBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - protocolBinding_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object tenant_ = ""; - /** - *
-     * Tenant to be set in the request when calling the agent.
-     * 
- * - * string tenant = 3; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Tenant to be set in the request when calling the agent.
-     * 
- * - * string tenant = 3; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Tenant to be set in the request when calling the agent.
-     * 
- * - * string tenant = 3; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * Tenant to be set in the request when calling the agent.
-     * 
- * - * string tenant = 3; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * Tenant to be set in the request when calling the agent.
-     * 
- * - * string tenant = 3; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private java.lang.Object protocolVersion_ = ""; - /** - *
-     * The version of the A2A protocol this interface exposes.
-     * Use the latest supported minor version per major version.
-     * Examples: "0.3", "1.0"
-     * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolVersion. - */ - public java.lang.String getProtocolVersion() { - java.lang.Object ref = protocolVersion_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - protocolVersion_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The version of the A2A protocol this interface exposes.
-     * Use the latest supported minor version per major version.
-     * Examples: "0.3", "1.0"
-     * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolVersion. - */ - public com.google.protobuf.ByteString - getProtocolVersionBytes() { - java.lang.Object ref = protocolVersion_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - protocolVersion_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The version of the A2A protocol this interface exposes.
-     * Use the latest supported minor version per major version.
-     * Examples: "0.3", "1.0"
-     * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The protocolVersion to set. - * @return This builder for chaining. - */ - public Builder setProtocolVersion( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - protocolVersion_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * The version of the A2A protocol this interface exposes.
-     * Use the latest supported minor version per major version.
-     * Examples: "0.3", "1.0"
-     * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearProtocolVersion() { - protocolVersion_ = getDefaultInstance().getProtocolVersion(); - bitField0_ = (bitField0_ & ~0x00000008); - onChanged(); - return this; - } - /** - *
-     * The version of the A2A protocol this interface exposes.
-     * Use the latest supported minor version per major version.
-     * Examples: "0.3", "1.0"
-     * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for protocolVersion to set. - * @return This builder for chaining. - */ - public Builder setProtocolVersionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - protocolVersion_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentInterface) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AgentInterface) - private static final io.a2a.grpc.AgentInterface DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AgentInterface(); - } - - public static io.a2a.grpc.AgentInterface getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AgentInterface parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AgentInterface getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java deleted file mode 100644 index 3dfe76f41..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentInterfaceOrBuilder.java +++ /dev/null @@ -1,102 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AgentInterfaceOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentInterface) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-   * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - java.lang.String getUrl(); - /** - *
-   * The URL where this interface is available. Must be a valid absolute HTTPS URL in production.
-   * Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - com.google.protobuf.ByteString - getUrlBytes(); - - /** - *
-   * The protocol binding supported at this URL. This is an open form string, to be
-   * easily extended for other protocol bindings. The core ones officially
-   * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-   * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolBinding. - */ - java.lang.String getProtocolBinding(); - /** - *
-   * The protocol binding supported at this URL. This is an open form string, to be
-   * easily extended for other protocol bindings. The core ones officially
-   * supported are `JSONRPC`, `GRPC` and `HTTP+JSON`.
-   * 
- * - * string protocol_binding = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolBinding. - */ - com.google.protobuf.ByteString - getProtocolBindingBytes(); - - /** - *
-   * Tenant to be set in the request when calling the agent.
-   * 
- * - * string tenant = 3; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Tenant to be set in the request when calling the agent.
-   * 
- * - * string tenant = 3; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The version of the A2A protocol this interface exposes.
-   * Use the latest supported minor version per major version.
-   * Examples: "0.3", "1.0"
-   * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The protocolVersion. - */ - java.lang.String getProtocolVersion(); - /** - *
-   * The version of the A2A protocol this interface exposes.
-   * Use the latest supported minor version per major version.
-   * Examples: "0.3", "1.0"
-   * 
- * - * string protocol_version = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for protocolVersion. - */ - com.google.protobuf.ByteString - getProtocolVersionBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java deleted file mode 100644 index fdd9402a3..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentProvider.java +++ /dev/null @@ -1,718 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AgentProvider]
- * Represents the service provider of an agent.
- * 
- * - * Protobuf type {@code a2a.v1.AgentProvider} - */ -@com.google.protobuf.Generated -public final class AgentProvider extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentProvider) - AgentProviderOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AgentProvider"); - } - // Use AgentProvider.newBuilder() to construct. - private AgentProvider(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AgentProvider() { - url_ = ""; - organization_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentProvider.class, io.a2a.grpc.AgentProvider.Builder.class); - } - - public static final int URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object url_ = ""; - /** - *
-   * A URL for the agent provider's website or relevant documentation.
-   * Example: "https://ai.google.dev"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - @java.lang.Override - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } - } - /** - *
-   * A URL for the agent provider's website or relevant documentation.
-   * Example: "https://ai.google.dev"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ORGANIZATION_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object organization_ = ""; - /** - *
-   * The name of the agent provider's organization.
-   * Example: "Google"
-   * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The organization. - */ - @java.lang.Override - public java.lang.String getOrganization() { - java.lang.Object ref = organization_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - organization_ = s; - return s; - } - } - /** - *
-   * The name of the agent provider's organization.
-   * Example: "Google"
-   * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for organization. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getOrganizationBytes() { - java.lang.Object ref = organization_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - organization_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(organization_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, organization_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(organization_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, organization_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AgentProvider)) { - return super.equals(obj); - } - io.a2a.grpc.AgentProvider other = (io.a2a.grpc.AgentProvider) obj; - - if (!getUrl() - .equals(other.getUrl())) return false; - if (!getOrganization() - .equals(other.getOrganization())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + URL_FIELD_NUMBER; - hash = (53 * hash) + getUrl().hashCode(); - hash = (37 * hash) + ORGANIZATION_FIELD_NUMBER; - hash = (53 * hash) + getOrganization().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AgentProvider parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentProvider parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentProvider parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentProvider parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentProvider parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentProvider parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentProvider parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentProvider parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AgentProvider parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AgentProvider parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AgentProvider parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentProvider parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AgentProvider prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AgentProvider]
-   * Represents the service provider of an agent.
-   * 
- * - * Protobuf type {@code a2a.v1.AgentProvider} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentProvider) - io.a2a.grpc.AgentProviderOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentProvider.class, io.a2a.grpc.AgentProvider.Builder.class); - } - - // Construct using io.a2a.grpc.AgentProvider.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - url_ = ""; - organization_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentProvider_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AgentProvider getDefaultInstanceForType() { - return io.a2a.grpc.AgentProvider.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AgentProvider build() { - io.a2a.grpc.AgentProvider result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AgentProvider buildPartial() { - io.a2a.grpc.AgentProvider result = new io.a2a.grpc.AgentProvider(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.AgentProvider result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.url_ = url_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.organization_ = organization_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AgentProvider) { - return mergeFrom((io.a2a.grpc.AgentProvider)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AgentProvider other) { - if (other == io.a2a.grpc.AgentProvider.getDefaultInstance()) return this; - if (!other.getUrl().isEmpty()) { - url_ = other.url_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getOrganization().isEmpty()) { - organization_ = other.organization_; - bitField0_ |= 0x00000002; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - url_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - organization_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object url_ = ""; - /** - *
-     * A URL for the agent provider's website or relevant documentation.
-     * Example: "https://ai.google.dev"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A URL for the agent provider's website or relevant documentation.
-     * Example: "https://ai.google.dev"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A URL for the agent provider's website or relevant documentation.
-     * Example: "https://ai.google.dev"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The url to set. - * @return This builder for chaining. - */ - public Builder setUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - url_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * A URL for the agent provider's website or relevant documentation.
-     * Example: "https://ai.google.dev"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearUrl() { - url_ = getDefaultInstance().getUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * A URL for the agent provider's website or relevant documentation.
-     * Example: "https://ai.google.dev"
-     * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for url to set. - * @return This builder for chaining. - */ - public Builder setUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - url_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object organization_ = ""; - /** - *
-     * The name of the agent provider's organization.
-     * Example: "Google"
-     * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The organization. - */ - public java.lang.String getOrganization() { - java.lang.Object ref = organization_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - organization_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The name of the agent provider's organization.
-     * Example: "Google"
-     * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for organization. - */ - public com.google.protobuf.ByteString - getOrganizationBytes() { - java.lang.Object ref = organization_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - organization_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The name of the agent provider's organization.
-     * Example: "Google"
-     * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The organization to set. - * @return This builder for chaining. - */ - public Builder setOrganization( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - organization_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The name of the agent provider's organization.
-     * Example: "Google"
-     * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearOrganization() { - organization_ = getDefaultInstance().getOrganization(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The name of the agent provider's organization.
-     * Example: "Google"
-     * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for organization to set. - * @return This builder for chaining. - */ - public Builder setOrganizationBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - organization_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentProvider) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AgentProvider) - private static final io.a2a.grpc.AgentProvider DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AgentProvider(); - } - - public static io.a2a.grpc.AgentProvider getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AgentProvider parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AgentProvider getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java deleted file mode 100644 index a0e2efefa..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentProviderOrBuilder.java +++ /dev/null @@ -1,56 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AgentProviderOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentProvider) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * A URL for the agent provider's website or relevant documentation.
-   * Example: "https://ai.google.dev"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - java.lang.String getUrl(); - /** - *
-   * A URL for the agent provider's website or relevant documentation.
-   * Example: "https://ai.google.dev"
-   * 
- * - * string url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - com.google.protobuf.ByteString - getUrlBytes(); - - /** - *
-   * The name of the agent provider's organization.
-   * Example: "Google"
-   * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The organization. - */ - java.lang.String getOrganization(); - /** - *
-   * The name of the agent provider's organization.
-   * Example: "Google"
-   * 
- * - * string organization = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for organization. - */ - com.google.protobuf.ByteString - getOrganizationBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java deleted file mode 100644 index 087596019..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkill.java +++ /dev/null @@ -1,2278 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AgentSkill]
- * Represents a distinct capability or function that an agent can perform.
- * 
- * - * Protobuf type {@code a2a.v1.AgentSkill} - */ -@com.google.protobuf.Generated -public final class AgentSkill extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AgentSkill) - AgentSkillOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AgentSkill"); - } - // Use AgentSkill.newBuilder() to construct. - private AgentSkill(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AgentSkill() { - id_ = ""; - name_ = ""; - description_ = ""; - tags_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - examples_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - inputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - outputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - securityRequirements_ = java.util.Collections.emptyList(); - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentSkill.class, io.a2a.grpc.AgentSkill.Builder.class); - } - - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * A unique identifier for the agent's skill.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * A unique identifier for the agent's skill.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int NAME_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; - /** - *
-   * A human-readable name for the skill.
-   * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } - } - /** - *
-   * A human-readable name for the skill.
-   * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int DESCRIPTION_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * A detailed description of the skill.
-   * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * A detailed description of the skill.
-   * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TAGS_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList tags_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the tags. - */ - public com.google.protobuf.ProtocolStringList - getTagsList() { - return tags_; - } - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of tags. - */ - public int getTagsCount() { - return tags_.size(); - } - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The tags at the given index. - */ - public java.lang.String getTags(int index) { - return tags_.get(index); - } - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the tags at the given index. - */ - public com.google.protobuf.ByteString - getTagsBytes(int index) { - return tags_.getByteString(index); - } - - public static final int EXAMPLES_FIELD_NUMBER = 5; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList examples_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @return A list containing the examples. - */ - public com.google.protobuf.ProtocolStringList - getExamplesList() { - return examples_; - } - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @return The count of examples. - */ - public int getExamplesCount() { - return examples_.size(); - } - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @param index The index of the element to return. - * @return The examples at the given index. - */ - public java.lang.String getExamples(int index) { - return examples_.get(index); - } - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @param index The index of the value to return. - * @return The bytes of the examples at the given index. - */ - public com.google.protobuf.ByteString - getExamplesBytes(int index) { - return examples_.getByteString(index); - } - - public static final int INPUT_MODES_FIELD_NUMBER = 6; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList inputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @return A list containing the inputModes. - */ - public com.google.protobuf.ProtocolStringList - getInputModesList() { - return inputModes_; - } - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @return The count of inputModes. - */ - public int getInputModesCount() { - return inputModes_.size(); - } - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @param index The index of the element to return. - * @return The inputModes at the given index. - */ - public java.lang.String getInputModes(int index) { - return inputModes_.get(index); - } - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @param index The index of the value to return. - * @return The bytes of the inputModes at the given index. - */ - public com.google.protobuf.ByteString - getInputModesBytes(int index) { - return inputModes_.getByteString(index); - } - - public static final int OUTPUT_MODES_FIELD_NUMBER = 7; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList outputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @return A list containing the outputModes. - */ - public com.google.protobuf.ProtocolStringList - getOutputModesList() { - return outputModes_; - } - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @return The count of outputModes. - */ - public int getOutputModesCount() { - return outputModes_.size(); - } - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @param index The index of the element to return. - * @return The outputModes at the given index. - */ - public java.lang.String getOutputModes(int index) { - return outputModes_.get(index); - } - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @param index The index of the value to return. - * @return The bytes of the outputModes at the given index. - */ - public com.google.protobuf.ByteString - getOutputModesBytes(int index) { - return outputModes_.getByteString(index); - } - - public static final int SECURITY_REQUIREMENTS_FIELD_NUMBER = 8; - @SuppressWarnings("serial") - private java.util.List securityRequirements_; - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - @java.lang.Override - public java.util.List getSecurityRequirementsList() { - return securityRequirements_; - } - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - @java.lang.Override - public java.util.List - getSecurityRequirementsOrBuilderList() { - return securityRequirements_; - } - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - @java.lang.Override - public int getSecurityRequirementsCount() { - return securityRequirements_.size(); - } - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - @java.lang.Override - public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { - return securityRequirements_.get(index); - } - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - @java.lang.Override - public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( - int index) { - return securityRequirements_.get(index); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, name_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, description_); - } - for (int i = 0; i < tags_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tags_.getRaw(i)); - } - for (int i = 0; i < examples_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 5, examples_.getRaw(i)); - } - for (int i = 0; i < inputModes_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 6, inputModes_.getRaw(i)); - } - for (int i = 0; i < outputModes_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 7, outputModes_.getRaw(i)); - } - for (int i = 0; i < securityRequirements_.size(); i++) { - output.writeMessage(8, securityRequirements_.get(i)); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, name_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, description_); - } - { - int dataSize = 0; - for (int i = 0; i < tags_.size(); i++) { - dataSize += computeStringSizeNoTag(tags_.getRaw(i)); - } - size += dataSize; - size += 1 * getTagsList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < examples_.size(); i++) { - dataSize += computeStringSizeNoTag(examples_.getRaw(i)); - } - size += dataSize; - size += 1 * getExamplesList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < inputModes_.size(); i++) { - dataSize += computeStringSizeNoTag(inputModes_.getRaw(i)); - } - size += dataSize; - size += 1 * getInputModesList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < outputModes_.size(); i++) { - dataSize += computeStringSizeNoTag(outputModes_.getRaw(i)); - } - size += dataSize; - size += 1 * getOutputModesList().size(); - } - for (int i = 0; i < securityRequirements_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(8, securityRequirements_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AgentSkill)) { - return super.equals(obj); - } - io.a2a.grpc.AgentSkill other = (io.a2a.grpc.AgentSkill) obj; - - if (!getId() - .equals(other.getId())) return false; - if (!getName() - .equals(other.getName())) return false; - if (!getDescription() - .equals(other.getDescription())) return false; - if (!getTagsList() - .equals(other.getTagsList())) return false; - if (!getExamplesList() - .equals(other.getExamplesList())) return false; - if (!getInputModesList() - .equals(other.getInputModesList())) return false; - if (!getOutputModesList() - .equals(other.getOutputModesList())) return false; - if (!getSecurityRequirementsList() - .equals(other.getSecurityRequirementsList())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - if (getTagsCount() > 0) { - hash = (37 * hash) + TAGS_FIELD_NUMBER; - hash = (53 * hash) + getTagsList().hashCode(); - } - if (getExamplesCount() > 0) { - hash = (37 * hash) + EXAMPLES_FIELD_NUMBER; - hash = (53 * hash) + getExamplesList().hashCode(); - } - if (getInputModesCount() > 0) { - hash = (37 * hash) + INPUT_MODES_FIELD_NUMBER; - hash = (53 * hash) + getInputModesList().hashCode(); - } - if (getOutputModesCount() > 0) { - hash = (37 * hash) + OUTPUT_MODES_FIELD_NUMBER; - hash = (53 * hash) + getOutputModesList().hashCode(); - } - if (getSecurityRequirementsCount() > 0) { - hash = (37 * hash) + SECURITY_REQUIREMENTS_FIELD_NUMBER; - hash = (53 * hash) + getSecurityRequirementsList().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AgentSkill parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentSkill parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentSkill parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentSkill parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentSkill parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AgentSkill parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AgentSkill parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentSkill parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AgentSkill parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AgentSkill parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AgentSkill parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AgentSkill parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AgentSkill prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AgentSkill]
-   * Represents a distinct capability or function that an agent can perform.
-   * 
- * - * Protobuf type {@code a2a.v1.AgentSkill} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AgentSkill) - io.a2a.grpc.AgentSkillOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AgentSkill.class, io.a2a.grpc.AgentSkill.Builder.class); - } - - // Construct using io.a2a.grpc.AgentSkill.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - id_ = ""; - name_ = ""; - description_ = ""; - tags_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - examples_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - inputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - outputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - if (securityRequirementsBuilder_ == null) { - securityRequirements_ = java.util.Collections.emptyList(); - } else { - securityRequirements_ = null; - securityRequirementsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000080); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AgentSkill_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AgentSkill getDefaultInstanceForType() { - return io.a2a.grpc.AgentSkill.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AgentSkill build() { - io.a2a.grpc.AgentSkill result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AgentSkill buildPartial() { - io.a2a.grpc.AgentSkill result = new io.a2a.grpc.AgentSkill(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.AgentSkill result) { - if (securityRequirementsBuilder_ == null) { - if (((bitField0_ & 0x00000080) != 0)) { - securityRequirements_ = java.util.Collections.unmodifiableList(securityRequirements_); - bitField0_ = (bitField0_ & ~0x00000080); - } - result.securityRequirements_ = securityRequirements_; - } else { - result.securityRequirements_ = securityRequirementsBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.AgentSkill result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.id_ = id_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.name_ = name_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.description_ = description_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - tags_.makeImmutable(); - result.tags_ = tags_; - } - if (((from_bitField0_ & 0x00000010) != 0)) { - examples_.makeImmutable(); - result.examples_ = examples_; - } - if (((from_bitField0_ & 0x00000020) != 0)) { - inputModes_.makeImmutable(); - result.inputModes_ = inputModes_; - } - if (((from_bitField0_ & 0x00000040) != 0)) { - outputModes_.makeImmutable(); - result.outputModes_ = outputModes_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AgentSkill) { - return mergeFrom((io.a2a.grpc.AgentSkill)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AgentSkill other) { - if (other == io.a2a.grpc.AgentSkill.getDefaultInstance()) return this; - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getName().isEmpty()) { - name_ = other.name_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (!other.tags_.isEmpty()) { - if (tags_.isEmpty()) { - tags_ = other.tags_; - bitField0_ |= 0x00000008; - } else { - ensureTagsIsMutable(); - tags_.addAll(other.tags_); - } - onChanged(); - } - if (!other.examples_.isEmpty()) { - if (examples_.isEmpty()) { - examples_ = other.examples_; - bitField0_ |= 0x00000010; - } else { - ensureExamplesIsMutable(); - examples_.addAll(other.examples_); - } - onChanged(); - } - if (!other.inputModes_.isEmpty()) { - if (inputModes_.isEmpty()) { - inputModes_ = other.inputModes_; - bitField0_ |= 0x00000020; - } else { - ensureInputModesIsMutable(); - inputModes_.addAll(other.inputModes_); - } - onChanged(); - } - if (!other.outputModes_.isEmpty()) { - if (outputModes_.isEmpty()) { - outputModes_ = other.outputModes_; - bitField0_ |= 0x00000040; - } else { - ensureOutputModesIsMutable(); - outputModes_.addAll(other.outputModes_); - } - onChanged(); - } - if (securityRequirementsBuilder_ == null) { - if (!other.securityRequirements_.isEmpty()) { - if (securityRequirements_.isEmpty()) { - securityRequirements_ = other.securityRequirements_; - bitField0_ = (bitField0_ & ~0x00000080); - } else { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.addAll(other.securityRequirements_); - } - onChanged(); - } - } else { - if (!other.securityRequirements_.isEmpty()) { - if (securityRequirementsBuilder_.isEmpty()) { - securityRequirementsBuilder_.dispose(); - securityRequirementsBuilder_ = null; - securityRequirements_ = other.securityRequirements_; - bitField0_ = (bitField0_ & ~0x00000080); - securityRequirementsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetSecurityRequirementsFieldBuilder() : null; - } else { - securityRequirementsBuilder_.addAllMessages(other.securityRequirements_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - java.lang.String s = input.readStringRequireUtf8(); - ensureTagsIsMutable(); - tags_.add(s); - break; - } // case 34 - case 42: { - java.lang.String s = input.readStringRequireUtf8(); - ensureExamplesIsMutable(); - examples_.add(s); - break; - } // case 42 - case 50: { - java.lang.String s = input.readStringRequireUtf8(); - ensureInputModesIsMutable(); - inputModes_.add(s); - break; - } // case 50 - case 58: { - java.lang.String s = input.readStringRequireUtf8(); - ensureOutputModesIsMutable(); - outputModes_.add(s); - break; - } // case 58 - case 66: { - io.a2a.grpc.SecurityRequirement m = - input.readMessage( - io.a2a.grpc.SecurityRequirement.parser(), - extensionRegistry); - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(m); - } else { - securityRequirementsBuilder_.addMessage(m); - } - break; - } // case 66 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object id_ = ""; - /** - *
-     * A unique identifier for the agent's skill.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A unique identifier for the agent's skill.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A unique identifier for the agent's skill.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * A unique identifier for the agent's skill.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * A unique identifier for the agent's skill.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object name_ = ""; - /** - *
-     * A human-readable name for the skill.
-     * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A human-readable name for the skill.
-     * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A human-readable name for the skill.
-     * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The name to set. - * @return This builder for chaining. - */ - public Builder setName( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - name_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * A human-readable name for the skill.
-     * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * A human-readable name for the skill.
-     * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for name to set. - * @return This builder for chaining. - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - name_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object description_ = ""; - /** - *
-     * A detailed description of the skill.
-     * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A detailed description of the skill.
-     * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A detailed description of the skill.
-     * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * A detailed description of the skill.
-     * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * A detailed description of the skill.
-     * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private com.google.protobuf.LazyStringArrayList tags_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureTagsIsMutable() { - if (!tags_.isModifiable()) { - tags_ = new com.google.protobuf.LazyStringArrayList(tags_); - } - bitField0_ |= 0x00000008; - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the tags. - */ - public com.google.protobuf.ProtocolStringList - getTagsList() { - tags_.makeImmutable(); - return tags_; - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of tags. - */ - public int getTagsCount() { - return tags_.size(); - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The tags at the given index. - */ - public java.lang.String getTags(int index) { - return tags_.get(index); - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the tags at the given index. - */ - public com.google.protobuf.ByteString - getTagsBytes(int index) { - return tags_.getByteString(index); - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index to set the value at. - * @param value The tags to set. - * @return This builder for chaining. - */ - public Builder setTags( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureTagsIsMutable(); - tags_.set(index, value); - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The tags to add. - * @return This builder for chaining. - */ - public Builder addTags( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureTagsIsMutable(); - tags_.add(value); - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param values The tags to add. - * @return This builder for chaining. - */ - public Builder addAllTags( - java.lang.Iterable values) { - ensureTagsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, tags_); - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTags() { - tags_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008);; - onChanged(); - return this; - } - /** - *
-     * A set of keywords describing the skill's capabilities.
-     * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes of the tags to add. - * @return This builder for chaining. - */ - public Builder addTagsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureTagsIsMutable(); - tags_.add(value); - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - - private com.google.protobuf.LazyStringArrayList examples_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureExamplesIsMutable() { - if (!examples_.isModifiable()) { - examples_ = new com.google.protobuf.LazyStringArrayList(examples_); - } - bitField0_ |= 0x00000010; - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @return A list containing the examples. - */ - public com.google.protobuf.ProtocolStringList - getExamplesList() { - examples_.makeImmutable(); - return examples_; - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @return The count of examples. - */ - public int getExamplesCount() { - return examples_.size(); - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @param index The index of the element to return. - * @return The examples at the given index. - */ - public java.lang.String getExamples(int index) { - return examples_.get(index); - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @param index The index of the value to return. - * @return The bytes of the examples at the given index. - */ - public com.google.protobuf.ByteString - getExamplesBytes(int index) { - return examples_.getByteString(index); - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @param index The index to set the value at. - * @param value The examples to set. - * @return This builder for chaining. - */ - public Builder setExamples( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureExamplesIsMutable(); - examples_.set(index, value); - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @param value The examples to add. - * @return This builder for chaining. - */ - public Builder addExamples( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureExamplesIsMutable(); - examples_.add(value); - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @param values The examples to add. - * @return This builder for chaining. - */ - public Builder addAllExamples( - java.lang.Iterable values) { - ensureExamplesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, examples_); - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @return This builder for chaining. - */ - public Builder clearExamples() { - examples_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000010);; - onChanged(); - return this; - } - /** - *
-     * Example prompts or scenarios that this skill can handle.
-     * 
- * - * repeated string examples = 5; - * @param value The bytes of the examples to add. - * @return This builder for chaining. - */ - public Builder addExamplesBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureExamplesIsMutable(); - examples_.add(value); - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - - private com.google.protobuf.LazyStringArrayList inputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureInputModesIsMutable() { - if (!inputModes_.isModifiable()) { - inputModes_ = new com.google.protobuf.LazyStringArrayList(inputModes_); - } - bitField0_ |= 0x00000020; - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @return A list containing the inputModes. - */ - public com.google.protobuf.ProtocolStringList - getInputModesList() { - inputModes_.makeImmutable(); - return inputModes_; - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @return The count of inputModes. - */ - public int getInputModesCount() { - return inputModes_.size(); - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @param index The index of the element to return. - * @return The inputModes at the given index. - */ - public java.lang.String getInputModes(int index) { - return inputModes_.get(index); - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @param index The index of the value to return. - * @return The bytes of the inputModes at the given index. - */ - public com.google.protobuf.ByteString - getInputModesBytes(int index) { - return inputModes_.getByteString(index); - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @param index The index to set the value at. - * @param value The inputModes to set. - * @return This builder for chaining. - */ - public Builder setInputModes( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureInputModesIsMutable(); - inputModes_.set(index, value); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @param value The inputModes to add. - * @return This builder for chaining. - */ - public Builder addInputModes( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureInputModesIsMutable(); - inputModes_.add(value); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @param values The inputModes to add. - * @return This builder for chaining. - */ - public Builder addAllInputModes( - java.lang.Iterable values) { - ensureInputModesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, inputModes_); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @return This builder for chaining. - */ - public Builder clearInputModes() { - inputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000020);; - onChanged(); - return this; - } - /** - *
-     * The set of supported input media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string input_modes = 6; - * @param value The bytes of the inputModes to add. - * @return This builder for chaining. - */ - public Builder addInputModesBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureInputModesIsMutable(); - inputModes_.add(value); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - - private com.google.protobuf.LazyStringArrayList outputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureOutputModesIsMutable() { - if (!outputModes_.isModifiable()) { - outputModes_ = new com.google.protobuf.LazyStringArrayList(outputModes_); - } - bitField0_ |= 0x00000040; - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @return A list containing the outputModes. - */ - public com.google.protobuf.ProtocolStringList - getOutputModesList() { - outputModes_.makeImmutable(); - return outputModes_; - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @return The count of outputModes. - */ - public int getOutputModesCount() { - return outputModes_.size(); - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @param index The index of the element to return. - * @return The outputModes at the given index. - */ - public java.lang.String getOutputModes(int index) { - return outputModes_.get(index); - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @param index The index of the value to return. - * @return The bytes of the outputModes at the given index. - */ - public com.google.protobuf.ByteString - getOutputModesBytes(int index) { - return outputModes_.getByteString(index); - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @param index The index to set the value at. - * @param value The outputModes to set. - * @return This builder for chaining. - */ - public Builder setOutputModes( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureOutputModesIsMutable(); - outputModes_.set(index, value); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @param value The outputModes to add. - * @return This builder for chaining. - */ - public Builder addOutputModes( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureOutputModesIsMutable(); - outputModes_.add(value); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @param values The outputModes to add. - * @return This builder for chaining. - */ - public Builder addAllOutputModes( - java.lang.Iterable values) { - ensureOutputModesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, outputModes_); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @return This builder for chaining. - */ - public Builder clearOutputModes() { - outputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000040);; - onChanged(); - return this; - } - /** - *
-     * The set of supported output media types for this skill, overriding the agent's defaults.
-     * 
- * - * repeated string output_modes = 7; - * @param value The bytes of the outputModes to add. - * @return This builder for chaining. - */ - public Builder addOutputModesBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureOutputModesIsMutable(); - outputModes_.add(value); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - - private java.util.List securityRequirements_ = - java.util.Collections.emptyList(); - private void ensureSecurityRequirementsIsMutable() { - if (!((bitField0_ & 0x00000080) != 0)) { - securityRequirements_ = new java.util.ArrayList(securityRequirements_); - bitField0_ |= 0x00000080; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> securityRequirementsBuilder_; - - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public java.util.List getSecurityRequirementsList() { - if (securityRequirementsBuilder_ == null) { - return java.util.Collections.unmodifiableList(securityRequirements_); - } else { - return securityRequirementsBuilder_.getMessageList(); - } - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public int getSecurityRequirementsCount() { - if (securityRequirementsBuilder_ == null) { - return securityRequirements_.size(); - } else { - return securityRequirementsBuilder_.getCount(); - } - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index) { - if (securityRequirementsBuilder_ == null) { - return securityRequirements_.get(index); - } else { - return securityRequirementsBuilder_.getMessage(index); - } - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder setSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement value) { - if (securityRequirementsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSecurityRequirementsIsMutable(); - securityRequirements_.set(index, value); - onChanged(); - } else { - securityRequirementsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder setSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.set(index, builderForValue.build()); - onChanged(); - } else { - securityRequirementsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder addSecurityRequirements(io.a2a.grpc.SecurityRequirement value) { - if (securityRequirementsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(value); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder addSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement value) { - if (securityRequirementsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(index, value); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder addSecurityRequirements( - io.a2a.grpc.SecurityRequirement.Builder builderForValue) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(builderForValue.build()); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder addSecurityRequirements( - int index, io.a2a.grpc.SecurityRequirement.Builder builderForValue) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.add(index, builderForValue.build()); - onChanged(); - } else { - securityRequirementsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder addAllSecurityRequirements( - java.lang.Iterable values) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, securityRequirements_); - onChanged(); - } else { - securityRequirementsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder clearSecurityRequirements() { - if (securityRequirementsBuilder_ == null) { - securityRequirements_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000080); - onChanged(); - } else { - securityRequirementsBuilder_.clear(); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public Builder removeSecurityRequirements(int index) { - if (securityRequirementsBuilder_ == null) { - ensureSecurityRequirementsIsMutable(); - securityRequirements_.remove(index); - onChanged(); - } else { - securityRequirementsBuilder_.remove(index); - } - return this; - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public io.a2a.grpc.SecurityRequirement.Builder getSecurityRequirementsBuilder( - int index) { - return internalGetSecurityRequirementsFieldBuilder().getBuilder(index); - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( - int index) { - if (securityRequirementsBuilder_ == null) { - return securityRequirements_.get(index); } else { - return securityRequirementsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public java.util.List - getSecurityRequirementsOrBuilderList() { - if (securityRequirementsBuilder_ != null) { - return securityRequirementsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(securityRequirements_); - } - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder() { - return internalGetSecurityRequirementsFieldBuilder().addBuilder( - io.a2a.grpc.SecurityRequirement.getDefaultInstance()); - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public io.a2a.grpc.SecurityRequirement.Builder addSecurityRequirementsBuilder( - int index) { - return internalGetSecurityRequirementsFieldBuilder().addBuilder( - index, io.a2a.grpc.SecurityRequirement.getDefaultInstance()); - } - /** - *
-     * Security schemes necessary for this skill.
-     * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - public java.util.List - getSecurityRequirementsBuilderList() { - return internalGetSecurityRequirementsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder> - internalGetSecurityRequirementsFieldBuilder() { - if (securityRequirementsBuilder_ == null) { - securityRequirementsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.SecurityRequirement, io.a2a.grpc.SecurityRequirement.Builder, io.a2a.grpc.SecurityRequirementOrBuilder>( - securityRequirements_, - ((bitField0_ & 0x00000080) != 0), - getParentForChildren(), - isClean()); - securityRequirements_ = null; - } - return securityRequirementsBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AgentSkill) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AgentSkill) - private static final io.a2a.grpc.AgentSkill DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AgentSkill(); - } - - public static io.a2a.grpc.AgentSkill getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AgentSkill parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AgentSkill getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java deleted file mode 100644 index 8cb65a6c5..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AgentSkillOrBuilder.java +++ /dev/null @@ -1,280 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AgentSkillOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AgentSkill) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * A unique identifier for the agent's skill.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * A unique identifier for the agent's skill.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - *
-   * A human-readable name for the skill.
-   * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The name. - */ - java.lang.String getName(); - /** - *
-   * A human-readable name for the skill.
-   * 
- * - * string name = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for name. - */ - com.google.protobuf.ByteString - getNameBytes(); - - /** - *
-   * A detailed description of the skill.
-   * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * A detailed description of the skill.
-   * 
- * - * string description = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return A list containing the tags. - */ - java.util.List - getTagsList(); - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The count of tags. - */ - int getTagsCount(); - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the element to return. - * @return The tags at the given index. - */ - java.lang.String getTags(int index); - /** - *
-   * A set of keywords describing the skill's capabilities.
-   * 
- * - * repeated string tags = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param index The index of the value to return. - * @return The bytes of the tags at the given index. - */ - com.google.protobuf.ByteString - getTagsBytes(int index); - - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @return A list containing the examples. - */ - java.util.List - getExamplesList(); - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @return The count of examples. - */ - int getExamplesCount(); - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @param index The index of the element to return. - * @return The examples at the given index. - */ - java.lang.String getExamples(int index); - /** - *
-   * Example prompts or scenarios that this skill can handle.
-   * 
- * - * repeated string examples = 5; - * @param index The index of the value to return. - * @return The bytes of the examples at the given index. - */ - com.google.protobuf.ByteString - getExamplesBytes(int index); - - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @return A list containing the inputModes. - */ - java.util.List - getInputModesList(); - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @return The count of inputModes. - */ - int getInputModesCount(); - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @param index The index of the element to return. - * @return The inputModes at the given index. - */ - java.lang.String getInputModes(int index); - /** - *
-   * The set of supported input media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string input_modes = 6; - * @param index The index of the value to return. - * @return The bytes of the inputModes at the given index. - */ - com.google.protobuf.ByteString - getInputModesBytes(int index); - - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @return A list containing the outputModes. - */ - java.util.List - getOutputModesList(); - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @return The count of outputModes. - */ - int getOutputModesCount(); - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @param index The index of the element to return. - * @return The outputModes at the given index. - */ - java.lang.String getOutputModes(int index); - /** - *
-   * The set of supported output media types for this skill, overriding the agent's defaults.
-   * 
- * - * repeated string output_modes = 7; - * @param index The index of the value to return. - * @return The bytes of the outputModes at the given index. - */ - com.google.protobuf.ByteString - getOutputModesBytes(int index); - - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - java.util.List - getSecurityRequirementsList(); - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - io.a2a.grpc.SecurityRequirement getSecurityRequirements(int index); - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - int getSecurityRequirementsCount(); - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - java.util.List - getSecurityRequirementsOrBuilderList(); - /** - *
-   * Security schemes necessary for this skill.
-   * 
- * - * repeated .a2a.v1.SecurityRequirement security_requirements = 8; - */ - io.a2a.grpc.SecurityRequirementOrBuilder getSecurityRequirementsOrBuilder( - int index); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java b/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java deleted file mode 100644 index 6716e86e2..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/Artifact.java +++ /dev/null @@ -1,1804 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:Artifact]
- * Artifacts represent task outputs.
- * 
- * - * Protobuf type {@code a2a.v1.Artifact} - */ -@com.google.protobuf.Generated -public final class Artifact extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Artifact) - ArtifactOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "Artifact"); - } - // Use Artifact.newBuilder() to construct. - private Artifact(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private Artifact() { - artifactId_ = ""; - name_ = ""; - description_ = ""; - parts_ = java.util.Collections.emptyList(); - extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Artifact.class, io.a2a.grpc.Artifact.Builder.class); - } - - private int bitField0_; - public static final int ARTIFACT_ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object artifactId_ = ""; - /** - *
-   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-   * within a task.
-   * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The artifactId. - */ - @java.lang.Override - public java.lang.String getArtifactId() { - java.lang.Object ref = artifactId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - artifactId_ = s; - return s; - } - } - /** - *
-   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-   * within a task.
-   * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for artifactId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getArtifactIdBytes() { - java.lang.Object ref = artifactId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - artifactId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int NAME_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object name_ = ""; - /** - *
-   * A human readable name for the artifact.
-   * 
- * - * string name = 3; - * @return The name. - */ - @java.lang.Override - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } - } - /** - *
-   * A human readable name for the artifact.
-   * 
- * - * string name = 3; - * @return The bytes for name. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int DESCRIPTION_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * A human readable description of the artifact, optional.
-   * 
- * - * string description = 4; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * A human readable description of the artifact, optional.
-   * 
- * - * string description = 4; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PARTS_FIELD_NUMBER = 5; - @SuppressWarnings("serial") - private java.util.List parts_; - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List getPartsList() { - return parts_; - } - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List - getPartsOrBuilderList() { - return parts_; - } - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public int getPartsCount() { - return parts_.size(); - } - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.Part getParts(int index) { - return parts_.get(index); - } - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( - int index) { - return parts_.get(index); - } - - public static final int METADATA_FIELD_NUMBER = 6; - private com.google.protobuf.Struct metadata_; - /** - *
-   * Optional metadata included with the artifact.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - @java.lang.Override - public boolean hasMetadata() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * Optional metadata included with the artifact.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - @java.lang.Override - public com.google.protobuf.Struct getMetadata() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - /** - *
-   * Optional metadata included with the artifact.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - - public static final int EXTENSIONS_FIELD_NUMBER = 7; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @return A list containing the extensions. - */ - public com.google.protobuf.ProtocolStringList - getExtensionsList() { - return extensions_; - } - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @return The count of extensions. - */ - public int getExtensionsCount() { - return extensions_.size(); - } - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the element to return. - * @return The extensions at the given index. - */ - public java.lang.String getExtensions(int index) { - return extensions_.get(index); - } - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the value to return. - * @return The bytes of the extensions at the given index. - */ - public com.google.protobuf.ByteString - getExtensionsBytes(int index) { - return extensions_.getByteString(index); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(artifactId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, artifactId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, name_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, description_); - } - for (int i = 0; i < parts_.size(); i++) { - output.writeMessage(5, parts_.get(i)); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(6, getMetadata()); - } - for (int i = 0; i < extensions_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 7, extensions_.getRaw(i)); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(artifactId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, artifactId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, name_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, description_); - } - for (int i = 0; i < parts_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, parts_.get(i)); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getMetadata()); - } - { - int dataSize = 0; - for (int i = 0; i < extensions_.size(); i++) { - dataSize += computeStringSizeNoTag(extensions_.getRaw(i)); - } - size += dataSize; - size += 1 * getExtensionsList().size(); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.Artifact)) { - return super.equals(obj); - } - io.a2a.grpc.Artifact other = (io.a2a.grpc.Artifact) obj; - - if (!getArtifactId() - .equals(other.getArtifactId())) return false; - if (!getName() - .equals(other.getName())) return false; - if (!getDescription() - .equals(other.getDescription())) return false; - if (!getPartsList() - .equals(other.getPartsList())) return false; - if (hasMetadata() != other.hasMetadata()) return false; - if (hasMetadata()) { - if (!getMetadata() - .equals(other.getMetadata())) return false; - } - if (!getExtensionsList() - .equals(other.getExtensionsList())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + ARTIFACT_ID_FIELD_NUMBER; - hash = (53 * hash) + getArtifactId().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - if (getPartsCount() > 0) { - hash = (37 * hash) + PARTS_FIELD_NUMBER; - hash = (53 * hash) + getPartsList().hashCode(); - } - if (hasMetadata()) { - hash = (37 * hash) + METADATA_FIELD_NUMBER; - hash = (53 * hash) + getMetadata().hashCode(); - } - if (getExtensionsCount() > 0) { - hash = (37 * hash) + EXTENSIONS_FIELD_NUMBER; - hash = (53 * hash) + getExtensionsList().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.Artifact parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Artifact parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Artifact parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Artifact parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Artifact parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Artifact parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Artifact parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Artifact parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.Artifact parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.Artifact parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.Artifact parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Artifact parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.Artifact prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:Artifact]
-   * Artifacts represent task outputs.
-   * 
- * - * Protobuf type {@code a2a.v1.Artifact} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Artifact) - io.a2a.grpc.ArtifactOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Artifact.class, io.a2a.grpc.Artifact.Builder.class); - } - - // Construct using io.a2a.grpc.Artifact.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetPartsFieldBuilder(); - internalGetMetadataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - artifactId_ = ""; - name_ = ""; - description_ = ""; - if (partsBuilder_ == null) { - parts_ = java.util.Collections.emptyList(); - } else { - parts_ = null; - partsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000008); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Artifact_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.Artifact getDefaultInstanceForType() { - return io.a2a.grpc.Artifact.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.Artifact build() { - io.a2a.grpc.Artifact result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.Artifact buildPartial() { - io.a2a.grpc.Artifact result = new io.a2a.grpc.Artifact(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.Artifact result) { - if (partsBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0)) { - parts_ = java.util.Collections.unmodifiableList(parts_); - bitField0_ = (bitField0_ & ~0x00000008); - } - result.parts_ = parts_; - } else { - result.parts_ = partsBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.Artifact result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.artifactId_ = artifactId_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.name_ = name_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.description_ = description_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000010) != 0)) { - result.metadata_ = metadataBuilder_ == null - ? metadata_ - : metadataBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000020) != 0)) { - extensions_.makeImmutable(); - result.extensions_ = extensions_; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.Artifact) { - return mergeFrom((io.a2a.grpc.Artifact)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.Artifact other) { - if (other == io.a2a.grpc.Artifact.getDefaultInstance()) return this; - if (!other.getArtifactId().isEmpty()) { - artifactId_ = other.artifactId_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getName().isEmpty()) { - name_ = other.name_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (partsBuilder_ == null) { - if (!other.parts_.isEmpty()) { - if (parts_.isEmpty()) { - parts_ = other.parts_; - bitField0_ = (bitField0_ & ~0x00000008); - } else { - ensurePartsIsMutable(); - parts_.addAll(other.parts_); - } - onChanged(); - } - } else { - if (!other.parts_.isEmpty()) { - if (partsBuilder_.isEmpty()) { - partsBuilder_.dispose(); - partsBuilder_ = null; - parts_ = other.parts_; - bitField0_ = (bitField0_ & ~0x00000008); - partsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetPartsFieldBuilder() : null; - } else { - partsBuilder_.addAllMessages(other.parts_); - } - } - } - if (other.hasMetadata()) { - mergeMetadata(other.getMetadata()); - } - if (!other.extensions_.isEmpty()) { - if (extensions_.isEmpty()) { - extensions_ = other.extensions_; - bitField0_ |= 0x00000020; - } else { - ensureExtensionsIsMutable(); - extensions_.addAll(other.extensions_); - } - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - artifactId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 26: { - name_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 26 - case 34: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 34 - case 42: { - io.a2a.grpc.Part m = - input.readMessage( - io.a2a.grpc.Part.parser(), - extensionRegistry); - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.add(m); - } else { - partsBuilder_.addMessage(m); - } - break; - } // case 42 - case 50: { - input.readMessage( - internalGetMetadataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000010; - break; - } // case 50 - case 58: { - java.lang.String s = input.readStringRequireUtf8(); - ensureExtensionsIsMutable(); - extensions_.add(s); - break; - } // case 58 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object artifactId_ = ""; - /** - *
-     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-     * within a task.
-     * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The artifactId. - */ - public java.lang.String getArtifactId() { - java.lang.Object ref = artifactId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - artifactId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-     * within a task.
-     * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for artifactId. - */ - public com.google.protobuf.ByteString - getArtifactIdBytes() { - java.lang.Object ref = artifactId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - artifactId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-     * within a task.
-     * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The artifactId to set. - * @return This builder for chaining. - */ - public Builder setArtifactId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - artifactId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-     * within a task.
-     * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearArtifactId() { - artifactId_ = getDefaultInstance().getArtifactId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-     * within a task.
-     * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for artifactId to set. - * @return This builder for chaining. - */ - public Builder setArtifactIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - artifactId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object name_ = ""; - /** - *
-     * A human readable name for the artifact.
-     * 
- * - * string name = 3; - * @return The name. - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A human readable name for the artifact.
-     * 
- * - * string name = 3; - * @return The bytes for name. - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A human readable name for the artifact.
-     * 
- * - * string name = 3; - * @param value The name to set. - * @return This builder for chaining. - */ - public Builder setName( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - name_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * A human readable name for the artifact.
-     * 
- * - * string name = 3; - * @return This builder for chaining. - */ - public Builder clearName() { - name_ = getDefaultInstance().getName(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * A human readable name for the artifact.
-     * 
- * - * string name = 3; - * @param value The bytes for name to set. - * @return This builder for chaining. - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - name_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object description_ = ""; - /** - *
-     * A human readable description of the artifact, optional.
-     * 
- * - * string description = 4; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A human readable description of the artifact, optional.
-     * 
- * - * string description = 4; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A human readable description of the artifact, optional.
-     * 
- * - * string description = 4; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * A human readable description of the artifact, optional.
-     * 
- * - * string description = 4; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * A human readable description of the artifact, optional.
-     * 
- * - * string description = 4; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private java.util.List parts_ = - java.util.Collections.emptyList(); - private void ensurePartsIsMutable() { - if (!((bitField0_ & 0x00000008) != 0)) { - parts_ = new java.util.ArrayList(parts_); - bitField0_ |= 0x00000008; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> partsBuilder_; - - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List getPartsList() { - if (partsBuilder_ == null) { - return java.util.Collections.unmodifiableList(parts_); - } else { - return partsBuilder_.getMessageList(); - } - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public int getPartsCount() { - if (partsBuilder_ == null) { - return parts_.size(); - } else { - return partsBuilder_.getCount(); - } - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part getParts(int index) { - if (partsBuilder_ == null) { - return parts_.get(index); - } else { - return partsBuilder_.getMessage(index); - } - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setParts( - int index, io.a2a.grpc.Part value) { - if (partsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensurePartsIsMutable(); - parts_.set(index, value); - onChanged(); - } else { - partsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setParts( - int index, io.a2a.grpc.Part.Builder builderForValue) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.set(index, builderForValue.build()); - onChanged(); - } else { - partsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts(io.a2a.grpc.Part value) { - if (partsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensurePartsIsMutable(); - parts_.add(value); - onChanged(); - } else { - partsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts( - int index, io.a2a.grpc.Part value) { - if (partsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensurePartsIsMutable(); - parts_.add(index, value); - onChanged(); - } else { - partsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts( - io.a2a.grpc.Part.Builder builderForValue) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.add(builderForValue.build()); - onChanged(); - } else { - partsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts( - int index, io.a2a.grpc.Part.Builder builderForValue) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.add(index, builderForValue.build()); - onChanged(); - } else { - partsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addAllParts( - java.lang.Iterable values) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, parts_); - onChanged(); - } else { - partsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearParts() { - if (partsBuilder_ == null) { - parts_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); - onChanged(); - } else { - partsBuilder_.clear(); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeParts(int index) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.remove(index); - onChanged(); - } else { - partsBuilder_.remove(index); - } - return this; - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part.Builder getPartsBuilder( - int index) { - return internalGetPartsFieldBuilder().getBuilder(index); - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( - int index) { - if (partsBuilder_ == null) { - return parts_.get(index); } else { - return partsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getPartsOrBuilderList() { - if (partsBuilder_ != null) { - return partsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(parts_); - } - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part.Builder addPartsBuilder() { - return internalGetPartsFieldBuilder().addBuilder( - io.a2a.grpc.Part.getDefaultInstance()); - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part.Builder addPartsBuilder( - int index) { - return internalGetPartsFieldBuilder().addBuilder( - index, io.a2a.grpc.Part.getDefaultInstance()); - } - /** - *
-     * The content of the artifact. Must contain at least one part.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getPartsBuilderList() { - return internalGetPartsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> - internalGetPartsFieldBuilder() { - if (partsBuilder_ == null) { - partsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder>( - parts_, - ((bitField0_ & 0x00000008) != 0), - getParentForChildren(), - isClean()); - parts_ = null; - } - return partsBuilder_; - } - - private com.google.protobuf.Struct metadata_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - public boolean hasMetadata() { - return ((bitField0_ & 0x00000010) != 0); - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - public com.google.protobuf.Struct getMetadata() { - if (metadataBuilder_ == null) { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } else { - return metadataBuilder_.getMessage(); - } - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - metadata_ = value; - } else { - metadataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata( - com.google.protobuf.Struct.Builder builderForValue) { - if (metadataBuilder_ == null) { - metadata_ = builderForValue.build(); - } else { - metadataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder mergeMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000010) != 0) && - metadata_ != null && - metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { - getMetadataBuilder().mergeFrom(value); - } else { - metadata_ = value; - } - } else { - metadataBuilder_.mergeFrom(value); - } - if (metadata_ != null) { - bitField0_ |= 0x00000010; - onChanged(); - } - return this; - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000010); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000010; - onChanged(); - return internalGetMetadataFieldBuilder().getBuilder(); - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - if (metadataBuilder_ != null) { - return metadataBuilder_.getMessageOrBuilder(); - } else { - return metadata_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - } - /** - *
-     * Optional metadata included with the artifact.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetMetadataFieldBuilder() { - if (metadataBuilder_ == null) { - metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getMetadata(), - getParentForChildren(), - isClean()); - metadata_ = null; - } - return metadataBuilder_; - } - - private com.google.protobuf.LazyStringArrayList extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureExtensionsIsMutable() { - if (!extensions_.isModifiable()) { - extensions_ = new com.google.protobuf.LazyStringArrayList(extensions_); - } - bitField0_ |= 0x00000020; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @return A list containing the extensions. - */ - public com.google.protobuf.ProtocolStringList - getExtensionsList() { - extensions_.makeImmutable(); - return extensions_; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @return The count of extensions. - */ - public int getExtensionsCount() { - return extensions_.size(); - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @param index The index of the element to return. - * @return The extensions at the given index. - */ - public java.lang.String getExtensions(int index) { - return extensions_.get(index); - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @param index The index of the value to return. - * @return The bytes of the extensions at the given index. - */ - public com.google.protobuf.ByteString - getExtensionsBytes(int index) { - return extensions_.getByteString(index); - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @param index The index to set the value at. - * @param value The extensions to set. - * @return This builder for chaining. - */ - public Builder setExtensions( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureExtensionsIsMutable(); - extensions_.set(index, value); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @param value The extensions to add. - * @return This builder for chaining. - */ - public Builder addExtensions( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureExtensionsIsMutable(); - extensions_.add(value); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @param values The extensions to add. - * @return This builder for chaining. - */ - public Builder addAllExtensions( - java.lang.Iterable values) { - ensureExtensionsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, extensions_); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @return This builder for chaining. - */ - public Builder clearExtensions() { - extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000020);; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Artifact.
-     * 
- * - * repeated string extensions = 7; - * @param value The bytes of the extensions to add. - * @return This builder for chaining. - */ - public Builder addExtensionsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureExtensionsIsMutable(); - extensions_.add(value); - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.Artifact) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.Artifact) - private static final io.a2a.grpc.Artifact DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.Artifact(); - } - - public static io.a2a.grpc.Artifact getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public Artifact parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.Artifact getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java deleted file mode 100644 index 3c1de141f..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ArtifactOrBuilder.java +++ /dev/null @@ -1,186 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ArtifactOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Artifact) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-   * within a task.
-   * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The artifactId. - */ - java.lang.String getArtifactId(); - /** - *
-   * Unique identifier (e.g. UUID) for the artifact. It must be at least unique
-   * within a task.
-   * 
- * - * string artifact_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for artifactId. - */ - com.google.protobuf.ByteString - getArtifactIdBytes(); - - /** - *
-   * A human readable name for the artifact.
-   * 
- * - * string name = 3; - * @return The name. - */ - java.lang.String getName(); - /** - *
-   * A human readable name for the artifact.
-   * 
- * - * string name = 3; - * @return The bytes for name. - */ - com.google.protobuf.ByteString - getNameBytes(); - - /** - *
-   * A human readable description of the artifact, optional.
-   * 
- * - * string description = 4; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * A human readable description of the artifact, optional.
-   * 
- * - * string description = 4; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getPartsList(); - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.Part getParts(int index); - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - int getPartsCount(); - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getPartsOrBuilderList(); - /** - *
-   * The content of the artifact. Must contain at least one part.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.PartOrBuilder getPartsOrBuilder( - int index); - - /** - *
-   * Optional metadata included with the artifact.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - boolean hasMetadata(); - /** - *
-   * Optional metadata included with the artifact.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - com.google.protobuf.Struct getMetadata(); - /** - *
-   * Optional metadata included with the artifact.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); - - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @return A list containing the extensions. - */ - java.util.List - getExtensionsList(); - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @return The count of extensions. - */ - int getExtensionsCount(); - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the element to return. - * @return The extensions at the given index. - */ - java.lang.String getExtensions(int index); - /** - *
-   * The URIs of extensions that are present or contributed to this Artifact.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the value to return. - * @return The bytes of the extensions at the given index. - */ - com.google.protobuf.ByteString - getExtensionsBytes(int index); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java deleted file mode 100644 index 703a6da52..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfo.java +++ /dev/null @@ -1,711 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:PushNotificationAuthenticationInfo]
- * Defines authentication details, used for push notifications.
- * 
- * - * Protobuf type {@code a2a.v1.AuthenticationInfo} - */ -@com.google.protobuf.Generated -public final class AuthenticationInfo extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AuthenticationInfo) - AuthenticationInfoOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AuthenticationInfo"); - } - // Use AuthenticationInfo.newBuilder() to construct. - private AuthenticationInfo(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AuthenticationInfo() { - scheme_ = ""; - credentials_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AuthenticationInfo.class, io.a2a.grpc.AuthenticationInfo.Builder.class); - } - - public static final int SCHEME_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object scheme_ = ""; - /** - *
-   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-   * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The scheme. - */ - @java.lang.Override - public java.lang.String getScheme() { - java.lang.Object ref = scheme_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - scheme_ = s; - return s; - } - } - /** - *
-   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-   * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for scheme. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getSchemeBytes() { - java.lang.Object ref = scheme_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - scheme_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CREDENTIALS_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object credentials_ = ""; - /** - *
-   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-   * 
- * - * string credentials = 2; - * @return The credentials. - */ - @java.lang.Override - public java.lang.String getCredentials() { - java.lang.Object ref = credentials_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - credentials_ = s; - return s; - } - } - /** - *
-   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-   * 
- * - * string credentials = 2; - * @return The bytes for credentials. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getCredentialsBytes() { - java.lang.Object ref = credentials_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - credentials_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, scheme_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(credentials_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, credentials_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, scheme_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(credentials_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, credentials_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AuthenticationInfo)) { - return super.equals(obj); - } - io.a2a.grpc.AuthenticationInfo other = (io.a2a.grpc.AuthenticationInfo) obj; - - if (!getScheme() - .equals(other.getScheme())) return false; - if (!getCredentials() - .equals(other.getCredentials())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + SCHEME_FIELD_NUMBER; - hash = (53 * hash) + getScheme().hashCode(); - hash = (37 * hash) + CREDENTIALS_FIELD_NUMBER; - hash = (53 * hash) + getCredentials().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AuthenticationInfo parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AuthenticationInfo parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AuthenticationInfo parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AuthenticationInfo parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AuthenticationInfo prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:PushNotificationAuthenticationInfo]
-   * Defines authentication details, used for push notifications.
-   * 
- * - * Protobuf type {@code a2a.v1.AuthenticationInfo} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AuthenticationInfo) - io.a2a.grpc.AuthenticationInfoOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AuthenticationInfo.class, io.a2a.grpc.AuthenticationInfo.Builder.class); - } - - // Construct using io.a2a.grpc.AuthenticationInfo.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - scheme_ = ""; - credentials_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthenticationInfo_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AuthenticationInfo getDefaultInstanceForType() { - return io.a2a.grpc.AuthenticationInfo.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AuthenticationInfo build() { - io.a2a.grpc.AuthenticationInfo result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AuthenticationInfo buildPartial() { - io.a2a.grpc.AuthenticationInfo result = new io.a2a.grpc.AuthenticationInfo(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.AuthenticationInfo result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.scheme_ = scheme_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.credentials_ = credentials_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AuthenticationInfo) { - return mergeFrom((io.a2a.grpc.AuthenticationInfo)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AuthenticationInfo other) { - if (other == io.a2a.grpc.AuthenticationInfo.getDefaultInstance()) return this; - if (!other.getScheme().isEmpty()) { - scheme_ = other.scheme_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getCredentials().isEmpty()) { - credentials_ = other.credentials_; - bitField0_ |= 0x00000002; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - scheme_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - credentials_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object scheme_ = ""; - /** - *
-     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-     * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The scheme. - */ - public java.lang.String getScheme() { - java.lang.Object ref = scheme_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - scheme_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-     * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for scheme. - */ - public com.google.protobuf.ByteString - getSchemeBytes() { - java.lang.Object ref = scheme_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - scheme_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-     * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The scheme to set. - * @return This builder for chaining. - */ - public Builder setScheme( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - scheme_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-     * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearScheme() { - scheme_ = getDefaultInstance().getScheme(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-     * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-     * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for scheme to set. - * @return This builder for chaining. - */ - public Builder setSchemeBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - scheme_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object credentials_ = ""; - /** - *
-     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-     * 
- * - * string credentials = 2; - * @return The credentials. - */ - public java.lang.String getCredentials() { - java.lang.Object ref = credentials_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - credentials_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-     * 
- * - * string credentials = 2; - * @return The bytes for credentials. - */ - public com.google.protobuf.ByteString - getCredentialsBytes() { - java.lang.Object ref = credentials_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - credentials_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-     * 
- * - * string credentials = 2; - * @param value The credentials to set. - * @return This builder for chaining. - */ - public Builder setCredentials( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - credentials_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-     * 
- * - * string credentials = 2; - * @return This builder for chaining. - */ - public Builder clearCredentials() { - credentials_ = getDefaultInstance().getCredentials(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-     * 
- * - * string credentials = 2; - * @param value The bytes for credentials to set. - * @return This builder for chaining. - */ - public Builder setCredentialsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - credentials_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AuthenticationInfo) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AuthenticationInfo) - private static final io.a2a.grpc.AuthenticationInfo DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AuthenticationInfo(); - } - - public static io.a2a.grpc.AuthenticationInfo getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AuthenticationInfo parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AuthenticationInfo getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java deleted file mode 100644 index b142c3670..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthenticationInfoOrBuilder.java +++ /dev/null @@ -1,54 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AuthenticationInfoOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AuthenticationInfo) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-   * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The scheme. - */ - java.lang.String getScheme(); - /** - *
-   * HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/).
-   * Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1).
-   * 
- * - * string scheme = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for scheme. - */ - com.google.protobuf.ByteString - getSchemeBytes(); - - /** - *
-   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-   * 
- * - * string credentials = 2; - * @return The credentials. - */ - java.lang.String getCredentials(); - /** - *
-   * Push Notification credentials. Format depends on the scheme (e.g., token for Bearer).
-   * 
- * - * string credentials = 2; - * @return The bytes for credentials. - */ - com.google.protobuf.ByteString - getCredentialsBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java deleted file mode 100644 index 06b7b8f41..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlow.java +++ /dev/null @@ -1,1278 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:AuthorizationCodeOAuthFlow]
- * Defines configuration details for the OAuth 2.0 Authorization Code flow.
- * 
- * - * Protobuf type {@code a2a.v1.AuthorizationCodeOAuthFlow} - */ -@com.google.protobuf.Generated -public final class AuthorizationCodeOAuthFlow extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.AuthorizationCodeOAuthFlow) - AuthorizationCodeOAuthFlowOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "AuthorizationCodeOAuthFlow"); - } - // Use AuthorizationCodeOAuthFlow.newBuilder() to construct. - private AuthorizationCodeOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private AuthorizationCodeOAuthFlow() { - authorizationUrl_ = ""; - tokenUrl_ = ""; - refreshUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 4: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AuthorizationCodeOAuthFlow.class, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder.class); - } - - public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object authorizationUrl_ = ""; - /** - *
-   * The authorization URL to be used for this flow.
-   * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The authorizationUrl. - */ - @java.lang.Override - public java.lang.String getAuthorizationUrl() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - authorizationUrl_ = s; - return s; - } - } - /** - *
-   * The authorization URL to be used for this flow.
-   * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for authorizationUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getAuthorizationUrlBytes() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - authorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TOKEN_URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object tokenUrl_ = ""; - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - @java.lang.Override - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } - } - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int REFRESH_URL_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object refreshUrl_ = ""; - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The refreshUrl. - */ - @java.lang.Override - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } - } - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The bytes for refreshUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SCOPES_FIELD_NUMBER = 4; - private static final class ScopesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_ScopesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public static final int PKCE_REQUIRED_FIELD_NUMBER = 5; - private boolean pkceRequired_ = false; - /** - *
-   * Indicates if PKCE (RFC 7636) is required for this flow.
-   * PKCE should always be used for public clients and is recommended for all clients.
-   * 
- * - * bool pkce_required = 5; - * @return The pkceRequired. - */ - @java.lang.Override - public boolean getPkceRequired() { - return pkceRequired_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, authorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, refreshUrl_); - } - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetScopes(), - ScopesDefaultEntryHolder.defaultEntry, - 4); - if (pkceRequired_ != false) { - output.writeBool(5, pkceRequired_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, authorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, refreshUrl_); - } - for (java.util.Map.Entry entry - : internalGetScopes().getMap().entrySet()) { - com.google.protobuf.MapEntry - scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, scopes__); - } - if (pkceRequired_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(5, pkceRequired_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.AuthorizationCodeOAuthFlow)) { - return super.equals(obj); - } - io.a2a.grpc.AuthorizationCodeOAuthFlow other = (io.a2a.grpc.AuthorizationCodeOAuthFlow) obj; - - if (!getAuthorizationUrl() - .equals(other.getAuthorizationUrl())) return false; - if (!getTokenUrl() - .equals(other.getTokenUrl())) return false; - if (!getRefreshUrl() - .equals(other.getRefreshUrl())) return false; - if (!internalGetScopes().equals( - other.internalGetScopes())) return false; - if (getPkceRequired() - != other.getPkceRequired()) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + AUTHORIZATION_URL_FIELD_NUMBER; - hash = (53 * hash) + getAuthorizationUrl().hashCode(); - hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; - hash = (53 * hash) + getTokenUrl().hashCode(); - hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; - hash = (53 * hash) + getRefreshUrl().hashCode(); - if (!internalGetScopes().getMap().isEmpty()) { - hash = (37 * hash) + SCOPES_FIELD_NUMBER; - hash = (53 * hash) + internalGetScopes().hashCode(); - } - hash = (37 * hash) + PKCE_REQUIRED_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getPkceRequired()); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.AuthorizationCodeOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.AuthorizationCodeOAuthFlow prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:AuthorizationCodeOAuthFlow]
-   * Defines configuration details for the OAuth 2.0 Authorization Code flow.
-   * 
- * - * Protobuf type {@code a2a.v1.AuthorizationCodeOAuthFlow} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.AuthorizationCodeOAuthFlow) - io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 4: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 4: - return internalGetMutableScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.AuthorizationCodeOAuthFlow.class, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder.class); - } - - // Construct using io.a2a.grpc.AuthorizationCodeOAuthFlow.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - authorizationUrl_ = ""; - tokenUrl_ = ""; - refreshUrl_ = ""; - internalGetMutableScopes().clear(); - pkceRequired_ = false; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_AuthorizationCodeOAuthFlow_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() { - return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlow build() { - io.a2a.grpc.AuthorizationCodeOAuthFlow result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlow buildPartial() { - io.a2a.grpc.AuthorizationCodeOAuthFlow result = new io.a2a.grpc.AuthorizationCodeOAuthFlow(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.AuthorizationCodeOAuthFlow result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.authorizationUrl_ = authorizationUrl_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.tokenUrl_ = tokenUrl_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.refreshUrl_ = refreshUrl_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.scopes_ = internalGetScopes(); - result.scopes_.makeImmutable(); - } - if (((from_bitField0_ & 0x00000010) != 0)) { - result.pkceRequired_ = pkceRequired_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.AuthorizationCodeOAuthFlow) { - return mergeFrom((io.a2a.grpc.AuthorizationCodeOAuthFlow)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.AuthorizationCodeOAuthFlow other) { - if (other == io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) return this; - if (!other.getAuthorizationUrl().isEmpty()) { - authorizationUrl_ = other.authorizationUrl_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getTokenUrl().isEmpty()) { - tokenUrl_ = other.tokenUrl_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getRefreshUrl().isEmpty()) { - refreshUrl_ = other.refreshUrl_; - bitField0_ |= 0x00000004; - onChanged(); - } - internalGetMutableScopes().mergeFrom( - other.internalGetScopes()); - bitField0_ |= 0x00000008; - if (other.getPkceRequired() != false) { - setPkceRequired(other.getPkceRequired()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - authorizationUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - tokenUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - refreshUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - com.google.protobuf.MapEntry - scopes__ = input.readMessage( - ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableScopes().getMutableMap().put( - scopes__.getKey(), scopes__.getValue()); - bitField0_ |= 0x00000008; - break; - } // case 34 - case 40: { - pkceRequired_ = input.readBool(); - bitField0_ |= 0x00000010; - break; - } // case 40 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object authorizationUrl_ = ""; - /** - *
-     * The authorization URL to be used for this flow.
-     * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The authorizationUrl. - */ - public java.lang.String getAuthorizationUrl() { - java.lang.Object ref = authorizationUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - authorizationUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The authorization URL to be used for this flow.
-     * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for authorizationUrl. - */ - public com.google.protobuf.ByteString - getAuthorizationUrlBytes() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - authorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The authorization URL to be used for this flow.
-     * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The authorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setAuthorizationUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - authorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The authorization URL to be used for this flow.
-     * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearAuthorizationUrl() { - authorizationUrl_ = getDefaultInstance().getAuthorizationUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The authorization URL to be used for this flow.
-     * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for authorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setAuthorizationUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - authorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object tokenUrl_ = ""; - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tokenUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTokenUrl() { - tokenUrl_ = getDefaultInstance().getTokenUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tokenUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object refreshUrl_ = ""; - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @return The refreshUrl. - */ - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @return The bytes for refreshUrl. - */ - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @param value The refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - refreshUrl_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @return This builder for chaining. - */ - public Builder clearRefreshUrl() { - refreshUrl_ = getDefaultInstance().getRefreshUrl(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @param value The bytes for refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - refreshUrl_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - private com.google.protobuf.MapField - internalGetMutableScopes() { - if (scopes_ == null) { - scopes_ = com.google.protobuf.MapField.newMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - if (!scopes_.isMutable()) { - scopes_ = scopes_.copy(); - } - bitField0_ |= 0x00000008; - onChanged(); - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - public Builder clearScopes() { - bitField0_ = (bitField0_ & ~0x00000008); - internalGetMutableScopes().getMutableMap() - .clear(); - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableScopes().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableScopes() { - bitField0_ |= 0x00000008; - return internalGetMutableScopes().getMutableMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putScopes( - java.lang.String key, - java.lang.String value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableScopes().getMutableMap() - .put(key, value); - bitField0_ |= 0x00000008; - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putAllScopes( - java.util.Map values) { - internalGetMutableScopes().getMutableMap() - .putAll(values); - bitField0_ |= 0x00000008; - return this; - } - - private boolean pkceRequired_ ; - /** - *
-     * Indicates if PKCE (RFC 7636) is required for this flow.
-     * PKCE should always be used for public clients and is recommended for all clients.
-     * 
- * - * bool pkce_required = 5; - * @return The pkceRequired. - */ - @java.lang.Override - public boolean getPkceRequired() { - return pkceRequired_; - } - /** - *
-     * Indicates if PKCE (RFC 7636) is required for this flow.
-     * PKCE should always be used for public clients and is recommended for all clients.
-     * 
- * - * bool pkce_required = 5; - * @param value The pkceRequired to set. - * @return This builder for chaining. - */ - public Builder setPkceRequired(boolean value) { - - pkceRequired_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Indicates if PKCE (RFC 7636) is required for this flow.
-     * PKCE should always be used for public clients and is recommended for all clients.
-     * 
- * - * bool pkce_required = 5; - * @return This builder for chaining. - */ - public Builder clearPkceRequired() { - bitField0_ = (bitField0_ & ~0x00000010); - pkceRequired_ = false; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.AuthorizationCodeOAuthFlow) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.AuthorizationCodeOAuthFlow) - private static final io.a2a.grpc.AuthorizationCodeOAuthFlow DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.AuthorizationCodeOAuthFlow(); - } - - public static io.a2a.grpc.AuthorizationCodeOAuthFlow getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public AuthorizationCodeOAuthFlow parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlow getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java deleted file mode 100644 index 5dd2d393d..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/AuthorizationCodeOAuthFlowOrBuilder.java +++ /dev/null @@ -1,137 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface AuthorizationCodeOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.AuthorizationCodeOAuthFlow) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The authorization URL to be used for this flow.
-   * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The authorizationUrl. - */ - java.lang.String getAuthorizationUrl(); - /** - *
-   * The authorization URL to be used for this flow.
-   * 
- * - * string authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for authorizationUrl. - */ - com.google.protobuf.ByteString - getAuthorizationUrlBytes(); - - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - java.lang.String getTokenUrl(); - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - com.google.protobuf.ByteString - getTokenUrlBytes(); - - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The refreshUrl. - */ - java.lang.String getRefreshUrl(); - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The bytes for refreshUrl. - */ - com.google.protobuf.ByteString - getRefreshUrlBytes(); - - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - int getScopesCount(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - boolean containsScopes( - java.lang.String key); - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getScopes(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.Map - getScopesMap(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - java.lang.String getScopesOrThrow( - java.lang.String key); - - /** - *
-   * Indicates if PKCE (RFC 7636) is required for this flow.
-   * PKCE should always be used for public clients and is recommended for all clients.
-   * 
- * - * bool pkce_required = 5; - * @return The pkceRequired. - */ - boolean getPkceRequired(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java deleted file mode 100644 index 3aa57435f..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequest.java +++ /dev/null @@ -1,704 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:CancelTaskRequest]
- * Represents a request for the `CancelTask` method.
- * 
- * - * Protobuf type {@code a2a.v1.CancelTaskRequest} - */ -@com.google.protobuf.Generated -public final class CancelTaskRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.CancelTaskRequest) - CancelTaskRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "CancelTaskRequest"); - } - // Use CancelTaskRequest.newBuilder() to construct. - private CancelTaskRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private CancelTaskRequest() { - tenant_ = ""; - id_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.CancelTaskRequest.class, io.a2a.grpc.CancelTaskRequest.Builder.class); - } - - public static final int TENANT_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * The resource id of the task to cancel.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * The resource id of the task to cancel.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.CancelTaskRequest)) { - return super.equals(obj); - } - io.a2a.grpc.CancelTaskRequest other = (io.a2a.grpc.CancelTaskRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getId() - .equals(other.getId())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.CancelTaskRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.CancelTaskRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.CancelTaskRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.CancelTaskRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.CancelTaskRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:CancelTaskRequest]
-   * Represents a request for the `CancelTask` method.
-   * 
- * - * Protobuf type {@code a2a.v1.CancelTaskRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.CancelTaskRequest) - io.a2a.grpc.CancelTaskRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.CancelTaskRequest.class, io.a2a.grpc.CancelTaskRequest.Builder.class); - } - - // Construct using io.a2a.grpc.CancelTaskRequest.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - id_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CancelTaskRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.CancelTaskRequest getDefaultInstanceForType() { - return io.a2a.grpc.CancelTaskRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.CancelTaskRequest build() { - io.a2a.grpc.CancelTaskRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.CancelTaskRequest buildPartial() { - io.a2a.grpc.CancelTaskRequest result = new io.a2a.grpc.CancelTaskRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.CancelTaskRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.id_ = id_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.CancelTaskRequest) { - return mergeFrom((io.a2a.grpc.CancelTaskRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.CancelTaskRequest other) { - if (other == io.a2a.grpc.CancelTaskRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000002; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 18 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object id_ = ""; - /** - *
-     * The resource id of the task to cancel.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The resource id of the task to cancel.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The resource id of the task to cancel.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The resource id of the task to cancel.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The resource id of the task to cancel.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.CancelTaskRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.CancelTaskRequest) - private static final io.a2a.grpc.CancelTaskRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.CancelTaskRequest(); - } - - public static io.a2a.grpc.CancelTaskRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public CancelTaskRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.CancelTaskRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java deleted file mode 100644 index 1e3251328..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/CancelTaskRequestOrBuilder.java +++ /dev/null @@ -1,52 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface CancelTaskRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.CancelTaskRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The resource id of the task to cancel.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * The resource id of the task to cancel.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java deleted file mode 100644 index 1af7c907c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlow.java +++ /dev/null @@ -1,1027 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:ClientCredentialsOAuthFlow]
- * Defines configuration details for the OAuth 2.0 Client Credentials flow.
- * 
- * - * Protobuf type {@code a2a.v1.ClientCredentialsOAuthFlow} - */ -@com.google.protobuf.Generated -public final class ClientCredentialsOAuthFlow extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ClientCredentialsOAuthFlow) - ClientCredentialsOAuthFlowOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "ClientCredentialsOAuthFlow"); - } - // Use ClientCredentialsOAuthFlow.newBuilder() to construct. - private ClientCredentialsOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private ClientCredentialsOAuthFlow() { - tokenUrl_ = ""; - refreshUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ClientCredentialsOAuthFlow.class, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder.class); - } - - public static final int TOKEN_URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object tokenUrl_ = ""; - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - @java.lang.Override - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } - } - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int REFRESH_URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object refreshUrl_ = ""; - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - @java.lang.Override - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } - } - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SCOPES_FIELD_NUMBER = 3; - private static final class ScopesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_ScopesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); - } - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetScopes(), - ScopesDefaultEntryHolder.defaultEntry, - 3); - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); - } - for (java.util.Map.Entry entry - : internalGetScopes().getMap().entrySet()) { - com.google.protobuf.MapEntry - scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, scopes__); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.ClientCredentialsOAuthFlow)) { - return super.equals(obj); - } - io.a2a.grpc.ClientCredentialsOAuthFlow other = (io.a2a.grpc.ClientCredentialsOAuthFlow) obj; - - if (!getTokenUrl() - .equals(other.getTokenUrl())) return false; - if (!getRefreshUrl() - .equals(other.getRefreshUrl())) return false; - if (!internalGetScopes().equals( - other.internalGetScopes())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; - hash = (53 * hash) + getTokenUrl().hashCode(); - hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; - hash = (53 * hash) + getRefreshUrl().hashCode(); - if (!internalGetScopes().getMap().isEmpty()) { - hash = (37 * hash) + SCOPES_FIELD_NUMBER; - hash = (53 * hash) + internalGetScopes().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ClientCredentialsOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.ClientCredentialsOAuthFlow prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:ClientCredentialsOAuthFlow]
-   * Defines configuration details for the OAuth 2.0 Client Credentials flow.
-   * 
- * - * Protobuf type {@code a2a.v1.ClientCredentialsOAuthFlow} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ClientCredentialsOAuthFlow) - io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetMutableScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ClientCredentialsOAuthFlow.class, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder.class); - } - - // Construct using io.a2a.grpc.ClientCredentialsOAuthFlow.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tokenUrl_ = ""; - refreshUrl_ = ""; - internalGetMutableScopes().clear(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ClientCredentialsOAuthFlow_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() { - return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlow build() { - io.a2a.grpc.ClientCredentialsOAuthFlow result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlow buildPartial() { - io.a2a.grpc.ClientCredentialsOAuthFlow result = new io.a2a.grpc.ClientCredentialsOAuthFlow(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.ClientCredentialsOAuthFlow result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tokenUrl_ = tokenUrl_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.refreshUrl_ = refreshUrl_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.scopes_ = internalGetScopes(); - result.scopes_.makeImmutable(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ClientCredentialsOAuthFlow) { - return mergeFrom((io.a2a.grpc.ClientCredentialsOAuthFlow)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.ClientCredentialsOAuthFlow other) { - if (other == io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) return this; - if (!other.getTokenUrl().isEmpty()) { - tokenUrl_ = other.tokenUrl_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getRefreshUrl().isEmpty()) { - refreshUrl_ = other.refreshUrl_; - bitField0_ |= 0x00000002; - onChanged(); - } - internalGetMutableScopes().mergeFrom( - other.internalGetScopes()); - bitField0_ |= 0x00000004; - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - tokenUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - refreshUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - com.google.protobuf.MapEntry - scopes__ = input.readMessage( - ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableScopes().getMutableMap().put( - scopes__.getKey(), scopes__.getValue()); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tokenUrl_ = ""; - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tokenUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTokenUrl() { - tokenUrl_ = getDefaultInstance().getTokenUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tokenUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object refreshUrl_ = ""; - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 2; - * @param value The refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 2; - * @return This builder for chaining. - */ - public Builder clearRefreshUrl() { - refreshUrl_ = getDefaultInstance().getRefreshUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 2; - * @param value The bytes for refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - private com.google.protobuf.MapField - internalGetMutableScopes() { - if (scopes_ == null) { - scopes_ = com.google.protobuf.MapField.newMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - if (!scopes_.isMutable()) { - scopes_ = scopes_.copy(); - } - bitField0_ |= 0x00000004; - onChanged(); - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - public Builder clearScopes() { - bitField0_ = (bitField0_ & ~0x00000004); - internalGetMutableScopes().getMutableMap() - .clear(); - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableScopes().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableScopes() { - bitField0_ |= 0x00000004; - return internalGetMutableScopes().getMutableMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putScopes( - java.lang.String key, - java.lang.String value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableScopes().getMutableMap() - .put(key, value); - bitField0_ |= 0x00000004; - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putAllScopes( - java.util.Map values) { - internalGetMutableScopes().getMutableMap() - .putAll(values); - bitField0_ |= 0x00000004; - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.ClientCredentialsOAuthFlow) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.ClientCredentialsOAuthFlow) - private static final io.a2a.grpc.ClientCredentialsOAuthFlow DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.ClientCredentialsOAuthFlow(); - } - - public static io.a2a.grpc.ClientCredentialsOAuthFlow getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ClientCredentialsOAuthFlow parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlow getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java deleted file mode 100644 index 4178ed50d..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ClientCredentialsOAuthFlowOrBuilder.java +++ /dev/null @@ -1,106 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ClientCredentialsOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ClientCredentialsOAuthFlow) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - java.lang.String getTokenUrl(); - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - com.google.protobuf.ByteString - getTokenUrlBytes(); - - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - java.lang.String getRefreshUrl(); - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - com.google.protobuf.ByteString - getRefreshUrlBytes(); - - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - int getScopesCount(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - boolean containsScopes( - java.lang.String key); - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getScopes(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.Map - getScopesMap(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - java.lang.String getScopesOrThrow( - java.lang.String key); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java deleted file mode 100644 index f445a86d2..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,1109 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:CreateTaskPushNotificationConfigRequest]
- * Represents a request for the `CreateTaskPushNotificationConfig` method.
- * 
- * - * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} - */ -@com.google.protobuf.Generated -public final class CreateTaskPushNotificationConfigRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) - CreateTaskPushNotificationConfigRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "CreateTaskPushNotificationConfigRequest"); - } - // Use CreateTaskPushNotificationConfigRequest.newBuilder() to construct. - private CreateTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private CreateTaskPushNotificationConfigRequest() { - tenant_ = ""; - taskId_ = ""; - configId_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); - } - - private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONFIG_ID_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object configId_ = ""; - /** - *
-   * The ID for the new config.
-   * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The configId. - */ - @java.lang.Override - public java.lang.String getConfigId() { - java.lang.Object ref = configId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - configId_ = s; - return s; - } - } - /** - *
-   * The ID for the new config.
-   * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for configId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getConfigIdBytes() { - java.lang.Object ref = configId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - configId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONFIG_FIELD_NUMBER = 5; - private io.a2a.grpc.PushNotificationConfig config_; - /** - *
-   * The configuration to create.
-   * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the config field is set. - */ - @java.lang.Override - public boolean hasConfig() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The configuration to create.
-   * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The config. - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getConfig() { - return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } - /** - *
-   * The configuration to create.
-   * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { - return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, configId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(5, getConfig()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(configId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, configId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, getConfig()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest)) { - return super.equals(obj); - } - io.a2a.grpc.CreateTaskPushNotificationConfigRequest other = (io.a2a.grpc.CreateTaskPushNotificationConfigRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (!getConfigId() - .equals(other.getConfigId())) return false; - if (hasConfig() != other.hasConfig()) return false; - if (hasConfig()) { - if (!getConfig() - .equals(other.getConfig())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + CONFIG_ID_FIELD_NUMBER; - hash = (53 * hash) + getConfigId().hashCode(); - if (hasConfig()) { - hash = (37 * hash) + CONFIG_FIELD_NUMBER; - hash = (53 * hash) + getConfig().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.CreateTaskPushNotificationConfigRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:CreateTaskPushNotificationConfigRequest]
-   * Represents a request for the `CreateTaskPushNotificationConfig` method.
-   * 
- * - * Protobuf type {@code a2a.v1.CreateTaskPushNotificationConfigRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.CreateTaskPushNotificationConfigRequest) - io.a2a.grpc.CreateTaskPushNotificationConfigRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.class, io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder.class); - } - - // Construct using io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetConfigFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - taskId_ = ""; - configId_ = ""; - config_ = null; - if (configBuilder_ != null) { - configBuilder_.dispose(); - configBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_CreateTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest build() { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest buildPartial() { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest result = new io.a2a.grpc.CreateTaskPushNotificationConfigRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.CreateTaskPushNotificationConfigRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.taskId_ = taskId_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.configId_ = configId_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { - result.config_ = configBuilder_ == null - ? config_ - : configBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest) { - return mergeFrom((io.a2a.grpc.CreateTaskPushNotificationConfigRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.CreateTaskPushNotificationConfigRequest other) { - if (other == io.a2a.grpc.CreateTaskPushNotificationConfigRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getConfigId().isEmpty()) { - configId_ = other.configId_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (other.hasConfig()) { - mergeConfig(other.getConfig()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 18: { - configId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 18 - case 34: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 34 - case 42: { - input.readMessage( - internalGetConfigFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 42 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object taskId_ = ""; - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object configId_ = ""; - /** - *
-     * The ID for the new config.
-     * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The configId. - */ - public java.lang.String getConfigId() { - java.lang.Object ref = configId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - configId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The ID for the new config.
-     * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for configId. - */ - public com.google.protobuf.ByteString - getConfigIdBytes() { - java.lang.Object ref = configId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - configId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The ID for the new config.
-     * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The configId to set. - * @return This builder for chaining. - */ - public Builder setConfigId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - configId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The ID for the new config.
-     * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearConfigId() { - configId_ = getDefaultInstance().getConfigId(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The ID for the new config.
-     * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for configId to set. - * @return This builder for chaining. - */ - public Builder setConfigIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - configId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private io.a2a.grpc.PushNotificationConfig config_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> configBuilder_; - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the config field is set. - */ - public boolean hasConfig() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The config. - */ - public io.a2a.grpc.PushNotificationConfig getConfig() { - if (configBuilder_ == null) { - return config_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } else { - return configBuilder_.getMessage(); - } - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setConfig(io.a2a.grpc.PushNotificationConfig value) { - if (configBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - config_ = value; - } else { - configBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setConfig( - io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { - if (configBuilder_ == null) { - config_ = builderForValue.build(); - } else { - configBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeConfig(io.a2a.grpc.PushNotificationConfig value) { - if (configBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - config_ != null && - config_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { - getConfigBuilder().mergeFrom(value); - } else { - config_ = value; - } - } else { - configBuilder_.mergeFrom(value); - } - if (config_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearConfig() { - bitField0_ = (bitField0_ & ~0x00000008); - config_ = null; - if (configBuilder_ != null) { - configBuilder_.dispose(); - configBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PushNotificationConfig.Builder getConfigBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetConfigFieldBuilder().getBuilder(); - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder() { - if (configBuilder_ != null) { - return configBuilder_.getMessageOrBuilder(); - } else { - return config_ == null ? - io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : config_; - } - } - /** - *
-     * The configuration to create.
-     * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> - internalGetConfigFieldBuilder() { - if (configBuilder_ == null) { - configBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder>( - getConfig(), - getParentForChildren(), - isClean()); - config_ = null; - } - return configBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.CreateTaskPushNotificationConfigRequest) - private static final io.a2a.grpc.CreateTaskPushNotificationConfigRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.CreateTaskPushNotificationConfigRequest(); - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public CreateTaskPushNotificationConfigRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.CreateTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java deleted file mode 100644 index 77a661f26..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/CreateTaskPushNotificationConfigRequestOrBuilder.java +++ /dev/null @@ -1,99 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface CreateTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.CreateTaskPushNotificationConfigRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * The ID for the new config.
-   * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The configId. - */ - java.lang.String getConfigId(); - /** - *
-   * The ID for the new config.
-   * 
- * - * string config_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for configId. - */ - com.google.protobuf.ByteString - getConfigIdBytes(); - - /** - *
-   * The configuration to create.
-   * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the config field is set. - */ - boolean hasConfig(); - /** - *
-   * The configuration to create.
-   * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - * @return The config. - */ - io.a2a.grpc.PushNotificationConfig getConfig(); - /** - *
-   * The configuration to create.
-   * 
- * - * .a2a.v1.PushNotificationConfig config = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.PushNotificationConfigOrBuilder getConfigOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java deleted file mode 100644 index bb1ac53b5..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,868 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:DeleteTaskPushNotificationConfigRequest]
- * Represents a request for the `DeleteTaskPushNotificationConfig` method.
- * 
- * - * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} - */ -@com.google.protobuf.Generated -public final class DeleteTaskPushNotificationConfigRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.DeleteTaskPushNotificationConfigRequest) - DeleteTaskPushNotificationConfigRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "DeleteTaskPushNotificationConfigRequest"); - } - // Use DeleteTaskPushNotificationConfigRequest.newBuilder() to construct. - private DeleteTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private DeleteTaskPushNotificationConfigRequest() { - tenant_ = ""; - taskId_ = ""; - id_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class); - } - - public static final int TENANT_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * The resource id of the config to delete.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * The resource id of the config to delete.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.DeleteTaskPushNotificationConfigRequest)) { - return super.equals(obj); - } - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest other = (io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (!getId() - .equals(other.getId())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:DeleteTaskPushNotificationConfigRequest]
-   * Represents a request for the `DeleteTaskPushNotificationConfig` method.
-   * 
- * - * Protobuf type {@code a2a.v1.DeleteTaskPushNotificationConfigRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.DeleteTaskPushNotificationConfigRequest) - io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.class, io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder.class); - } - - // Construct using io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - taskId_ = ""; - id_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeleteTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest build() { - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest buildPartial() { - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result = new io.a2a.grpc.DeleteTaskPushNotificationConfigRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.taskId_ = taskId_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.id_ = id_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) { - return mergeFrom((io.a2a.grpc.DeleteTaskPushNotificationConfigRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest other) { - if (other == io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000004; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 10 - case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 18 - case 26: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object taskId_ = ""; - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object id_ = ""; - /** - *
-     * The resource id of the config to delete.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The resource id of the config to delete.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The resource id of the config to delete.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The resource id of the config to delete.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The resource id of the config to delete.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.DeleteTaskPushNotificationConfigRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.DeleteTaskPushNotificationConfigRequest) - private static final io.a2a.grpc.DeleteTaskPushNotificationConfigRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.DeleteTaskPushNotificationConfigRequest(); - } - - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public DeleteTaskPushNotificationConfigRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.DeleteTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java deleted file mode 100644 index 4219aea04..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeleteTaskPushNotificationConfigRequestOrBuilder.java +++ /dev/null @@ -1,72 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface DeleteTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.DeleteTaskPushNotificationConfigRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * The resource id of the config to delete.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * The resource id of the config to delete.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java deleted file mode 100644 index 701371c2b..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlow.java +++ /dev/null @@ -1,1195 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:DeviceCodeOAuthFlow]
- * Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628).
- * This flow is designed for input-constrained devices such as IoT devices,
- * and CLI tools where the user authenticates on a separate device.
- * 
- * - * Protobuf type {@code a2a.v1.DeviceCodeOAuthFlow} - */ -@com.google.protobuf.Generated -public final class DeviceCodeOAuthFlow extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.DeviceCodeOAuthFlow) - DeviceCodeOAuthFlowOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "DeviceCodeOAuthFlow"); - } - // Use DeviceCodeOAuthFlow.newBuilder() to construct. - private DeviceCodeOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private DeviceCodeOAuthFlow() { - deviceAuthorizationUrl_ = ""; - tokenUrl_ = ""; - refreshUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 4: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class); - } - - public static final int DEVICE_AUTHORIZATION_URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object deviceAuthorizationUrl_ = ""; - /** - *
-   * The device authorization endpoint URL.
-   * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The deviceAuthorizationUrl. - */ - @java.lang.Override - public java.lang.String getDeviceAuthorizationUrl() { - java.lang.Object ref = deviceAuthorizationUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - deviceAuthorizationUrl_ = s; - return s; - } - } - /** - *
-   * The device authorization endpoint URL.
-   * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for deviceAuthorizationUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDeviceAuthorizationUrlBytes() { - java.lang.Object ref = deviceAuthorizationUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - deviceAuthorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TOKEN_URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object tokenUrl_ = ""; - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - @java.lang.Override - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } - } - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int REFRESH_URL_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object refreshUrl_ = ""; - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The refreshUrl. - */ - @java.lang.Override - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } - } - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The bytes for refreshUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SCOPES_FIELD_NUMBER = 4; - private static final class ScopesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_ScopesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(deviceAuthorizationUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, deviceAuthorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, refreshUrl_); - } - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetScopes(), - ScopesDefaultEntryHolder.defaultEntry, - 4); - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(deviceAuthorizationUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, deviceAuthorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, refreshUrl_); - } - for (java.util.Map.Entry entry - : internalGetScopes().getMap().entrySet()) { - com.google.protobuf.MapEntry - scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, scopes__); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.DeviceCodeOAuthFlow)) { - return super.equals(obj); - } - io.a2a.grpc.DeviceCodeOAuthFlow other = (io.a2a.grpc.DeviceCodeOAuthFlow) obj; - - if (!getDeviceAuthorizationUrl() - .equals(other.getDeviceAuthorizationUrl())) return false; - if (!getTokenUrl() - .equals(other.getTokenUrl())) return false; - if (!getRefreshUrl() - .equals(other.getRefreshUrl())) return false; - if (!internalGetScopes().equals( - other.internalGetScopes())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + DEVICE_AUTHORIZATION_URL_FIELD_NUMBER; - hash = (53 * hash) + getDeviceAuthorizationUrl().hashCode(); - hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; - hash = (53 * hash) + getTokenUrl().hashCode(); - hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; - hash = (53 * hash) + getRefreshUrl().hashCode(); - if (!internalGetScopes().getMap().isEmpty()) { - hash = (37 * hash) + SCOPES_FIELD_NUMBER; - hash = (53 * hash) + internalGetScopes().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.DeviceCodeOAuthFlow parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.DeviceCodeOAuthFlow parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.DeviceCodeOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.DeviceCodeOAuthFlow prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:DeviceCodeOAuthFlow]
-   * Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628).
-   * This flow is designed for input-constrained devices such as IoT devices,
-   * and CLI tools where the user authenticates on a separate device.
-   * 
- * - * Protobuf type {@code a2a.v1.DeviceCodeOAuthFlow} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.DeviceCodeOAuthFlow) - io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 4: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 4: - return internalGetMutableScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.DeviceCodeOAuthFlow.class, io.a2a.grpc.DeviceCodeOAuthFlow.Builder.class); - } - - // Construct using io.a2a.grpc.DeviceCodeOAuthFlow.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - deviceAuthorizationUrl_ = ""; - tokenUrl_ = ""; - refreshUrl_ = ""; - internalGetMutableScopes().clear(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_DeviceCodeOAuthFlow_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() { - return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlow build() { - io.a2a.grpc.DeviceCodeOAuthFlow result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlow buildPartial() { - io.a2a.grpc.DeviceCodeOAuthFlow result = new io.a2a.grpc.DeviceCodeOAuthFlow(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.DeviceCodeOAuthFlow result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.deviceAuthorizationUrl_ = deviceAuthorizationUrl_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.tokenUrl_ = tokenUrl_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.refreshUrl_ = refreshUrl_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.scopes_ = internalGetScopes(); - result.scopes_.makeImmutable(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.DeviceCodeOAuthFlow) { - return mergeFrom((io.a2a.grpc.DeviceCodeOAuthFlow)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.DeviceCodeOAuthFlow other) { - if (other == io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) return this; - if (!other.getDeviceAuthorizationUrl().isEmpty()) { - deviceAuthorizationUrl_ = other.deviceAuthorizationUrl_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getTokenUrl().isEmpty()) { - tokenUrl_ = other.tokenUrl_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getRefreshUrl().isEmpty()) { - refreshUrl_ = other.refreshUrl_; - bitField0_ |= 0x00000004; - onChanged(); - } - internalGetMutableScopes().mergeFrom( - other.internalGetScopes()); - bitField0_ |= 0x00000008; - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - deviceAuthorizationUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - tokenUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - refreshUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - com.google.protobuf.MapEntry - scopes__ = input.readMessage( - ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableScopes().getMutableMap().put( - scopes__.getKey(), scopes__.getValue()); - bitField0_ |= 0x00000008; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object deviceAuthorizationUrl_ = ""; - /** - *
-     * The device authorization endpoint URL.
-     * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The deviceAuthorizationUrl. - */ - public java.lang.String getDeviceAuthorizationUrl() { - java.lang.Object ref = deviceAuthorizationUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - deviceAuthorizationUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The device authorization endpoint URL.
-     * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for deviceAuthorizationUrl. - */ - public com.google.protobuf.ByteString - getDeviceAuthorizationUrlBytes() { - java.lang.Object ref = deviceAuthorizationUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - deviceAuthorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The device authorization endpoint URL.
-     * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The deviceAuthorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setDeviceAuthorizationUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - deviceAuthorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The device authorization endpoint URL.
-     * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearDeviceAuthorizationUrl() { - deviceAuthorizationUrl_ = getDefaultInstance().getDeviceAuthorizationUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The device authorization endpoint URL.
-     * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for deviceAuthorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setDeviceAuthorizationUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - deviceAuthorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object tokenUrl_ = ""; - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tokenUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTokenUrl() { - tokenUrl_ = getDefaultInstance().getTokenUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow.
-     * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tokenUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object refreshUrl_ = ""; - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @return The refreshUrl. - */ - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @return The bytes for refreshUrl. - */ - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @param value The refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - refreshUrl_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @return This builder for chaining. - */ - public Builder clearRefreshUrl() { - refreshUrl_ = getDefaultInstance().getRefreshUrl(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens.
-     * 
- * - * string refresh_url = 3; - * @param value The bytes for refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - refreshUrl_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - private com.google.protobuf.MapField - internalGetMutableScopes() { - if (scopes_ == null) { - scopes_ = com.google.protobuf.MapField.newMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - if (!scopes_.isMutable()) { - scopes_ = scopes_.copy(); - } - bitField0_ |= 0x00000008; - onChanged(); - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - public Builder clearScopes() { - bitField0_ = (bitField0_ & ~0x00000008); - internalGetMutableScopes().getMutableMap() - .clear(); - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableScopes().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableScopes() { - bitField0_ |= 0x00000008; - return internalGetMutableScopes().getMutableMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putScopes( - java.lang.String key, - java.lang.String value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableScopes().getMutableMap() - .put(key, value); - bitField0_ |= 0x00000008; - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme.
-     * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder putAllScopes( - java.util.Map values) { - internalGetMutableScopes().getMutableMap() - .putAll(values); - bitField0_ |= 0x00000008; - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.DeviceCodeOAuthFlow) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.DeviceCodeOAuthFlow) - private static final io.a2a.grpc.DeviceCodeOAuthFlow DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.DeviceCodeOAuthFlow(); - } - - public static io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public DeviceCodeOAuthFlow parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlow getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java deleted file mode 100644 index 761e2a6db..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/DeviceCodeOAuthFlowOrBuilder.java +++ /dev/null @@ -1,126 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface DeviceCodeOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.DeviceCodeOAuthFlow) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The device authorization endpoint URL.
-   * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The deviceAuthorizationUrl. - */ - java.lang.String getDeviceAuthorizationUrl(); - /** - *
-   * The device authorization endpoint URL.
-   * 
- * - * string device_authorization_url = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for deviceAuthorizationUrl. - */ - com.google.protobuf.ByteString - getDeviceAuthorizationUrlBytes(); - - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The tokenUrl. - */ - java.lang.String getTokenUrl(); - /** - *
-   * The token URL to be used for this flow.
-   * 
- * - * string token_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for tokenUrl. - */ - com.google.protobuf.ByteString - getTokenUrlBytes(); - - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The refreshUrl. - */ - java.lang.String getRefreshUrl(); - /** - *
-   * The URL to be used for obtaining refresh tokens.
-   * 
- * - * string refresh_url = 3; - * @return The bytes for refreshUrl. - */ - com.google.protobuf.ByteString - getRefreshUrlBytes(); - - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - int getScopesCount(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - boolean containsScopes( - java.lang.String key); - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getScopes(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.Map - getScopesMap(); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue); - /** - *
-   * The available scopes for the OAuth2 security scheme.
-   * 
- * - * map<string, string> scopes = 4 [(.google.api.field_behavior) = REQUIRED]; - */ - java.lang.String getScopesOrThrow( - java.lang.String key); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java deleted file mode 100644 index 5c1b07907..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequest.java +++ /dev/null @@ -1,538 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:GetExtendedAgentCardRequest]
- * 
- * - * Protobuf type {@code a2a.v1.GetExtendedAgentCardRequest} - */ -@com.google.protobuf.Generated -public final class GetExtendedAgentCardRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.GetExtendedAgentCardRequest) - GetExtendedAgentCardRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "GetExtendedAgentCardRequest"); - } - // Use GetExtendedAgentCardRequest.newBuilder() to construct. - private GetExtendedAgentCardRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private GetExtendedAgentCardRequest() { - tenant_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.GetExtendedAgentCardRequest.class, io.a2a.grpc.GetExtendedAgentCardRequest.Builder.class); - } - - public static final int TENANT_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 1; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 1; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.GetExtendedAgentCardRequest)) { - return super.equals(obj); - } - io.a2a.grpc.GetExtendedAgentCardRequest other = (io.a2a.grpc.GetExtendedAgentCardRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.GetExtendedAgentCardRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.GetExtendedAgentCardRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.GetExtendedAgentCardRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.GetExtendedAgentCardRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:GetExtendedAgentCardRequest]
-   * 
- * - * Protobuf type {@code a2a.v1.GetExtendedAgentCardRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.GetExtendedAgentCardRequest) - io.a2a.grpc.GetExtendedAgentCardRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.GetExtendedAgentCardRequest.class, io.a2a.grpc.GetExtendedAgentCardRequest.Builder.class); - } - - // Construct using io.a2a.grpc.GetExtendedAgentCardRequest.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetExtendedAgentCardRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.GetExtendedAgentCardRequest getDefaultInstanceForType() { - return io.a2a.grpc.GetExtendedAgentCardRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.GetExtendedAgentCardRequest build() { - io.a2a.grpc.GetExtendedAgentCardRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.GetExtendedAgentCardRequest buildPartial() { - io.a2a.grpc.GetExtendedAgentCardRequest result = new io.a2a.grpc.GetExtendedAgentCardRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.GetExtendedAgentCardRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.GetExtendedAgentCardRequest) { - return mergeFrom((io.a2a.grpc.GetExtendedAgentCardRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.GetExtendedAgentCardRequest other) { - if (other == io.a2a.grpc.GetExtendedAgentCardRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 1; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 1; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 1; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 1; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 1; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.GetExtendedAgentCardRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.GetExtendedAgentCardRequest) - private static final io.a2a.grpc.GetExtendedAgentCardRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.GetExtendedAgentCardRequest(); - } - - public static io.a2a.grpc.GetExtendedAgentCardRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public GetExtendedAgentCardRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.GetExtendedAgentCardRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java deleted file mode 100644 index f6efaa410..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetExtendedAgentCardRequestOrBuilder.java +++ /dev/null @@ -1,32 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface GetExtendedAgentCardRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.GetExtendedAgentCardRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 1; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 1; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java deleted file mode 100644 index e254a9022..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,866 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:GetTaskPushNotificationConfigRequest]
- * 
- * - * Protobuf type {@code a2a.v1.GetTaskPushNotificationConfigRequest} - */ -@com.google.protobuf.Generated -public final class GetTaskPushNotificationConfigRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.GetTaskPushNotificationConfigRequest) - GetTaskPushNotificationConfigRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "GetTaskPushNotificationConfigRequest"); - } - // Use GetTaskPushNotificationConfigRequest.newBuilder() to construct. - private GetTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private GetTaskPushNotificationConfigRequest() { - tenant_ = ""; - taskId_ = ""; - id_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder.class); - } - - public static final int TENANT_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * The resource id of the config to retrieve.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * The resource id of the config to retrieve.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.GetTaskPushNotificationConfigRequest)) { - return super.equals(obj); - } - io.a2a.grpc.GetTaskPushNotificationConfigRequest other = (io.a2a.grpc.GetTaskPushNotificationConfigRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (!getId() - .equals(other.getId())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.GetTaskPushNotificationConfigRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:GetTaskPushNotificationConfigRequest]
-   * 
- * - * Protobuf type {@code a2a.v1.GetTaskPushNotificationConfigRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.GetTaskPushNotificationConfigRequest) - io.a2a.grpc.GetTaskPushNotificationConfigRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.GetTaskPushNotificationConfigRequest.class, io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder.class); - } - - // Construct using io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - taskId_ = ""; - id_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return io.a2a.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.GetTaskPushNotificationConfigRequest build() { - io.a2a.grpc.GetTaskPushNotificationConfigRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.GetTaskPushNotificationConfigRequest buildPartial() { - io.a2a.grpc.GetTaskPushNotificationConfigRequest result = new io.a2a.grpc.GetTaskPushNotificationConfigRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.GetTaskPushNotificationConfigRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.taskId_ = taskId_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.id_ = id_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.GetTaskPushNotificationConfigRequest) { - return mergeFrom((io.a2a.grpc.GetTaskPushNotificationConfigRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.GetTaskPushNotificationConfigRequest other) { - if (other == io.a2a.grpc.GetTaskPushNotificationConfigRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000004; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 10 - case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 18 - case 26: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object taskId_ = ""; - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object id_ = ""; - /** - *
-     * The resource id of the config to retrieve.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The resource id of the config to retrieve.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The resource id of the config to retrieve.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The resource id of the config to retrieve.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The resource id of the config to retrieve.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.GetTaskPushNotificationConfigRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.GetTaskPushNotificationConfigRequest) - private static final io.a2a.grpc.GetTaskPushNotificationConfigRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.GetTaskPushNotificationConfigRequest(); - } - - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public GetTaskPushNotificationConfigRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.GetTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java deleted file mode 100644 index 5e9047f46..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskPushNotificationConfigRequestOrBuilder.java +++ /dev/null @@ -1,72 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface GetTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.GetTaskPushNotificationConfigRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * The resource id of the config to retrieve.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * The resource id of the config to retrieve.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java deleted file mode 100644 index 9fa872c52..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequest.java +++ /dev/null @@ -1,837 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:GetTaskRequest]
- * Represents a request for the `GetTask` method.
- * 
- * - * Protobuf type {@code a2a.v1.GetTaskRequest} - */ -@com.google.protobuf.Generated -public final class GetTaskRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.GetTaskRequest) - GetTaskRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "GetTaskRequest"); - } - // Use GetTaskRequest.newBuilder() to construct. - private GetTaskRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private GetTaskRequest() { - tenant_ = ""; - id_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.GetTaskRequest.class, io.a2a.grpc.GetTaskRequest.Builder.class); - } - - private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 3; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 3; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * The resource id of the task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * The resource id of the task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int HISTORY_LENGTH_FIELD_NUMBER = 2; - private int historyLength_ = 0; - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve. An
-   * unset value means the client does not impose any limit. A value of zero is
-   * a request to not include any messages. The server MUST NOT return more
-   * messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 2; - * @return Whether the historyLength field is set. - */ - @java.lang.Override - public boolean hasHistoryLength() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve. An
-   * unset value means the client does not impose any limit. A value of zero is
-   * a request to not include any messages. The server MUST NOT return more
-   * messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 2; - * @return The historyLength. - */ - @java.lang.Override - public int getHistoryLength() { - return historyLength_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeInt32(2, historyLength_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(2, historyLength_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.GetTaskRequest)) { - return super.equals(obj); - } - io.a2a.grpc.GetTaskRequest other = (io.a2a.grpc.GetTaskRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getId() - .equals(other.getId())) return false; - if (hasHistoryLength() != other.hasHistoryLength()) return false; - if (hasHistoryLength()) { - if (getHistoryLength() - != other.getHistoryLength()) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - if (hasHistoryLength()) { - hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; - hash = (53 * hash) + getHistoryLength(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.GetTaskRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetTaskRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetTaskRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetTaskRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetTaskRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.GetTaskRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.GetTaskRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.GetTaskRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.GetTaskRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.GetTaskRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.GetTaskRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.GetTaskRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.GetTaskRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:GetTaskRequest]
-   * Represents a request for the `GetTask` method.
-   * 
- * - * Protobuf type {@code a2a.v1.GetTaskRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.GetTaskRequest) - io.a2a.grpc.GetTaskRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.GetTaskRequest.class, io.a2a.grpc.GetTaskRequest.Builder.class); - } - - // Construct using io.a2a.grpc.GetTaskRequest.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - id_ = ""; - historyLength_ = 0; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_GetTaskRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.GetTaskRequest getDefaultInstanceForType() { - return io.a2a.grpc.GetTaskRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.GetTaskRequest build() { - io.a2a.grpc.GetTaskRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.GetTaskRequest buildPartial() { - io.a2a.grpc.GetTaskRequest result = new io.a2a.grpc.GetTaskRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.GetTaskRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.id_ = id_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.historyLength_ = historyLength_; - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.GetTaskRequest) { - return mergeFrom((io.a2a.grpc.GetTaskRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.GetTaskRequest other) { - if (other == io.a2a.grpc.GetTaskRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.hasHistoryLength()) { - setHistoryLength(other.getHistoryLength()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 16: { - historyLength_ = input.readInt32(); - bitField0_ |= 0x00000004; - break; - } // case 16 - case 26: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 3; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 3; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 3; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 3; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 3; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object id_ = ""; - /** - *
-     * The resource id of the task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The resource id of the task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The resource id of the task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The resource id of the task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The resource id of the task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private int historyLength_ ; - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve. An
-     * unset value means the client does not impose any limit. A value of zero is
-     * a request to not include any messages. The server MUST NOT return more
-     * messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 2; - * @return Whether the historyLength field is set. - */ - @java.lang.Override - public boolean hasHistoryLength() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve. An
-     * unset value means the client does not impose any limit. A value of zero is
-     * a request to not include any messages. The server MUST NOT return more
-     * messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 2; - * @return The historyLength. - */ - @java.lang.Override - public int getHistoryLength() { - return historyLength_; - } - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve. An
-     * unset value means the client does not impose any limit. A value of zero is
-     * a request to not include any messages. The server MUST NOT return more
-     * messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 2; - * @param value The historyLength to set. - * @return This builder for chaining. - */ - public Builder setHistoryLength(int value) { - - historyLength_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve. An
-     * unset value means the client does not impose any limit. A value of zero is
-     * a request to not include any messages. The server MUST NOT return more
-     * messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 2; - * @return This builder for chaining. - */ - public Builder clearHistoryLength() { - bitField0_ = (bitField0_ & ~0x00000004); - historyLength_ = 0; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.GetTaskRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.GetTaskRequest) - private static final io.a2a.grpc.GetTaskRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.GetTaskRequest(); - } - - public static io.a2a.grpc.GetTaskRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public GetTaskRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.GetTaskRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java deleted file mode 100644 index 7a86eb56c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/GetTaskRequestOrBuilder.java +++ /dev/null @@ -1,77 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface GetTaskRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.GetTaskRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 3; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 3; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The resource id of the task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * The resource id of the task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve. An
-   * unset value means the client does not impose any limit. A value of zero is
-   * a request to not include any messages. The server MUST NOT return more
-   * messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 2; - * @return Whether the historyLength field is set. - */ - boolean hasHistoryLength(); - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve. An
-   * unset value means the client does not impose any limit. A value of zero is
-   * a request to not include any messages. The server MUST NOT return more
-   * messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 2; - * @return The historyLength. - */ - int getHistoryLength(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java deleted file mode 100644 index cad53d0b9..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecurityScheme.java +++ /dev/null @@ -1,889 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:HTTPAuthSecurityScheme]
- * Defines a security scheme using HTTP authentication.
- * 
- * - * Protobuf type {@code a2a.v1.HTTPAuthSecurityScheme} - */ -@com.google.protobuf.Generated -public final class HTTPAuthSecurityScheme extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.HTTPAuthSecurityScheme) - HTTPAuthSecuritySchemeOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "HTTPAuthSecurityScheme"); - } - // Use HTTPAuthSecurityScheme.newBuilder() to construct. - private HTTPAuthSecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private HTTPAuthSecurityScheme() { - description_ = ""; - scheme_ = ""; - bearerFormat_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.HTTPAuthSecurityScheme.class, io.a2a.grpc.HTTPAuthSecurityScheme.Builder.class); - } - - public static final int DESCRIPTION_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SCHEME_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object scheme_ = ""; - /** - *
-   * The name of the HTTP Authentication scheme to be used in the Authorization header,
-   * as defined in RFC7235 (e.g., "Bearer").
-   * This value should be registered in the IANA Authentication Scheme registry.
-   * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The scheme. - */ - @java.lang.Override - public java.lang.String getScheme() { - java.lang.Object ref = scheme_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - scheme_ = s; - return s; - } - } - /** - *
-   * The name of the HTTP Authentication scheme to be used in the Authorization header,
-   * as defined in RFC7235 (e.g., "Bearer").
-   * This value should be registered in the IANA Authentication Scheme registry.
-   * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for scheme. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getSchemeBytes() { - java.lang.Object ref = scheme_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - scheme_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int BEARER_FORMAT_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object bearerFormat_ = ""; - /** - *
-   * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-   * This is primarily for documentation purposes.
-   * 
- * - * string bearer_format = 3; - * @return The bearerFormat. - */ - @java.lang.Override - public java.lang.String getBearerFormat() { - java.lang.Object ref = bearerFormat_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - bearerFormat_ = s; - return s; - } - } - /** - *
-   * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-   * This is primarily for documentation purposes.
-   * 
- * - * string bearer_format = 3; - * @return The bytes for bearerFormat. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getBearerFormatBytes() { - java.lang.Object ref = bearerFormat_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - bearerFormat_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, scheme_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(bearerFormat_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, bearerFormat_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(scheme_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, scheme_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(bearerFormat_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, bearerFormat_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.HTTPAuthSecurityScheme)) { - return super.equals(obj); - } - io.a2a.grpc.HTTPAuthSecurityScheme other = (io.a2a.grpc.HTTPAuthSecurityScheme) obj; - - if (!getDescription() - .equals(other.getDescription())) return false; - if (!getScheme() - .equals(other.getScheme())) return false; - if (!getBearerFormat() - .equals(other.getBearerFormat())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - hash = (37 * hash) + SCHEME_FIELD_NUMBER; - hash = (53 * hash) + getScheme().hashCode(); - hash = (37 * hash) + BEARER_FORMAT_FIELD_NUMBER; - hash = (53 * hash) + getBearerFormat().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.HTTPAuthSecurityScheme parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.HTTPAuthSecurityScheme parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.HTTPAuthSecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.HTTPAuthSecurityScheme prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:HTTPAuthSecurityScheme]
-   * Defines a security scheme using HTTP authentication.
-   * 
- * - * Protobuf type {@code a2a.v1.HTTPAuthSecurityScheme} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.HTTPAuthSecurityScheme) - io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.HTTPAuthSecurityScheme.class, io.a2a.grpc.HTTPAuthSecurityScheme.Builder.class); - } - - // Construct using io.a2a.grpc.HTTPAuthSecurityScheme.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - description_ = ""; - scheme_ = ""; - bearerFormat_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_HTTPAuthSecurityScheme_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() { - return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecurityScheme build() { - io.a2a.grpc.HTTPAuthSecurityScheme result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecurityScheme buildPartial() { - io.a2a.grpc.HTTPAuthSecurityScheme result = new io.a2a.grpc.HTTPAuthSecurityScheme(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.HTTPAuthSecurityScheme result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.description_ = description_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.scheme_ = scheme_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.bearerFormat_ = bearerFormat_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.HTTPAuthSecurityScheme) { - return mergeFrom((io.a2a.grpc.HTTPAuthSecurityScheme)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.HTTPAuthSecurityScheme other) { - if (other == io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) return this; - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getScheme().isEmpty()) { - scheme_ = other.scheme_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getBearerFormat().isEmpty()) { - bearerFormat_ = other.bearerFormat_; - bitField0_ |= 0x00000004; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - scheme_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - bearerFormat_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object description_ = ""; - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object scheme_ = ""; - /** - *
-     * The name of the HTTP Authentication scheme to be used in the Authorization header,
-     * as defined in RFC7235 (e.g., "Bearer").
-     * This value should be registered in the IANA Authentication Scheme registry.
-     * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The scheme. - */ - public java.lang.String getScheme() { - java.lang.Object ref = scheme_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - scheme_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The name of the HTTP Authentication scheme to be used in the Authorization header,
-     * as defined in RFC7235 (e.g., "Bearer").
-     * This value should be registered in the IANA Authentication Scheme registry.
-     * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for scheme. - */ - public com.google.protobuf.ByteString - getSchemeBytes() { - java.lang.Object ref = scheme_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - scheme_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The name of the HTTP Authentication scheme to be used in the Authorization header,
-     * as defined in RFC7235 (e.g., "Bearer").
-     * This value should be registered in the IANA Authentication Scheme registry.
-     * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The scheme to set. - * @return This builder for chaining. - */ - public Builder setScheme( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - scheme_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The name of the HTTP Authentication scheme to be used in the Authorization header,
-     * as defined in RFC7235 (e.g., "Bearer").
-     * This value should be registered in the IANA Authentication Scheme registry.
-     * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearScheme() { - scheme_ = getDefaultInstance().getScheme(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The name of the HTTP Authentication scheme to be used in the Authorization header,
-     * as defined in RFC7235 (e.g., "Bearer").
-     * This value should be registered in the IANA Authentication Scheme registry.
-     * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for scheme to set. - * @return This builder for chaining. - */ - public Builder setSchemeBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - scheme_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object bearerFormat_ = ""; - /** - *
-     * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-     * This is primarily for documentation purposes.
-     * 
- * - * string bearer_format = 3; - * @return The bearerFormat. - */ - public java.lang.String getBearerFormat() { - java.lang.Object ref = bearerFormat_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - bearerFormat_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-     * This is primarily for documentation purposes.
-     * 
- * - * string bearer_format = 3; - * @return The bytes for bearerFormat. - */ - public com.google.protobuf.ByteString - getBearerFormatBytes() { - java.lang.Object ref = bearerFormat_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - bearerFormat_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-     * This is primarily for documentation purposes.
-     * 
- * - * string bearer_format = 3; - * @param value The bearerFormat to set. - * @return This builder for chaining. - */ - public Builder setBearerFormat( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - bearerFormat_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-     * This is primarily for documentation purposes.
-     * 
- * - * string bearer_format = 3; - * @return This builder for chaining. - */ - public Builder clearBearerFormat() { - bearerFormat_ = getDefaultInstance().getBearerFormat(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-     * This is primarily for documentation purposes.
-     * 
- * - * string bearer_format = 3; - * @param value The bytes for bearerFormat to set. - * @return This builder for chaining. - */ - public Builder setBearerFormatBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - bearerFormat_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.HTTPAuthSecurityScheme) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.HTTPAuthSecurityScheme) - private static final io.a2a.grpc.HTTPAuthSecurityScheme DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.HTTPAuthSecurityScheme(); - } - - public static io.a2a.grpc.HTTPAuthSecurityScheme getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public HTTPAuthSecurityScheme parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecurityScheme getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java deleted file mode 100644 index 9a8e8847b..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/HTTPAuthSecuritySchemeOrBuilder.java +++ /dev/null @@ -1,78 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface HTTPAuthSecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.HTTPAuthSecurityScheme) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * The name of the HTTP Authentication scheme to be used in the Authorization header,
-   * as defined in RFC7235 (e.g., "Bearer").
-   * This value should be registered in the IANA Authentication Scheme registry.
-   * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The scheme. - */ - java.lang.String getScheme(); - /** - *
-   * The name of the HTTP Authentication scheme to be used in the Authorization header,
-   * as defined in RFC7235 (e.g., "Bearer").
-   * This value should be registered in the IANA Authentication Scheme registry.
-   * 
- * - * string scheme = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for scheme. - */ - com.google.protobuf.ByteString - getSchemeBytes(); - - /** - *
-   * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-   * This is primarily for documentation purposes.
-   * 
- * - * string bearer_format = 3; - * @return The bearerFormat. - */ - java.lang.String getBearerFormat(); - /** - *
-   * A hint to the client to identify how the bearer token is formatted (e.g., "JWT").
-   * This is primarily for documentation purposes.
-   * 
- * - * string bearer_format = 3; - * @return The bytes for bearerFormat. - */ - com.google.protobuf.ByteString - getBearerFormatBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java deleted file mode 100644 index e1fd0601c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlow.java +++ /dev/null @@ -1,1050 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * DEPRECATED
- * 
- * - * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} - */ -@com.google.protobuf.Generated -public final class ImplicitOAuthFlow extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ImplicitOAuthFlow) - ImplicitOAuthFlowOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "ImplicitOAuthFlow"); - } - // Use ImplicitOAuthFlow.newBuilder() to construct. - private ImplicitOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private ImplicitOAuthFlow() { - authorizationUrl_ = ""; - refreshUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); - } - - public static final int AUTHORIZATION_URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object authorizationUrl_ = ""; - /** - *
-   * The authorization URL to be used for this flow. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS
-   * 
- * - * string authorization_url = 1; - * @return The authorizationUrl. - */ - @java.lang.Override - public java.lang.String getAuthorizationUrl() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - authorizationUrl_ = s; - return s; - } - } - /** - *
-   * The authorization URL to be used for this flow. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS
-   * 
- * - * string authorization_url = 1; - * @return The bytes for authorizationUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getAuthorizationUrlBytes() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - authorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int REFRESH_URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object refreshUrl_ = ""; - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - @java.lang.Override - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } - } - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SCOPES_FIELD_NUMBER = 3; - private static final class ScopesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_ScopesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, authorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); - } - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetScopes(), - ScopesDefaultEntryHolder.defaultEntry, - 3); - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(authorizationUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, authorizationUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); - } - for (java.util.Map.Entry entry - : internalGetScopes().getMap().entrySet()) { - com.google.protobuf.MapEntry - scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, scopes__); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.ImplicitOAuthFlow)) { - return super.equals(obj); - } - io.a2a.grpc.ImplicitOAuthFlow other = (io.a2a.grpc.ImplicitOAuthFlow) obj; - - if (!getAuthorizationUrl() - .equals(other.getAuthorizationUrl())) return false; - if (!getRefreshUrl() - .equals(other.getRefreshUrl())) return false; - if (!internalGetScopes().equals( - other.internalGetScopes())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + AUTHORIZATION_URL_FIELD_NUMBER; - hash = (53 * hash) + getAuthorizationUrl().hashCode(); - hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; - hash = (53 * hash) + getRefreshUrl().hashCode(); - if (!internalGetScopes().getMap().isEmpty()) { - hash = (37 * hash) + SCOPES_FIELD_NUMBER; - hash = (53 * hash) + internalGetScopes().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.ImplicitOAuthFlow parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ImplicitOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.ImplicitOAuthFlow prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * DEPRECATED
-   * 
- * - * Protobuf type {@code a2a.v1.ImplicitOAuthFlow} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ImplicitOAuthFlow) - io.a2a.grpc.ImplicitOAuthFlowOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetMutableScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ImplicitOAuthFlow.class, io.a2a.grpc.ImplicitOAuthFlow.Builder.class); - } - - // Construct using io.a2a.grpc.ImplicitOAuthFlow.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - authorizationUrl_ = ""; - refreshUrl_ = ""; - internalGetMutableScopes().clear(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ImplicitOAuthFlow_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow build() { - io.a2a.grpc.ImplicitOAuthFlow result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow buildPartial() { - io.a2a.grpc.ImplicitOAuthFlow result = new io.a2a.grpc.ImplicitOAuthFlow(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.ImplicitOAuthFlow result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.authorizationUrl_ = authorizationUrl_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.refreshUrl_ = refreshUrl_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.scopes_ = internalGetScopes(); - result.scopes_.makeImmutable(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ImplicitOAuthFlow) { - return mergeFrom((io.a2a.grpc.ImplicitOAuthFlow)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.ImplicitOAuthFlow other) { - if (other == io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) return this; - if (!other.getAuthorizationUrl().isEmpty()) { - authorizationUrl_ = other.authorizationUrl_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getRefreshUrl().isEmpty()) { - refreshUrl_ = other.refreshUrl_; - bitField0_ |= 0x00000002; - onChanged(); - } - internalGetMutableScopes().mergeFrom( - other.internalGetScopes()); - bitField0_ |= 0x00000004; - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - authorizationUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - refreshUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - com.google.protobuf.MapEntry - scopes__ = input.readMessage( - ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableScopes().getMutableMap().put( - scopes__.getKey(), scopes__.getValue()); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object authorizationUrl_ = ""; - /** - *
-     * The authorization URL to be used for this flow. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS
-     * 
- * - * string authorization_url = 1; - * @return The authorizationUrl. - */ - public java.lang.String getAuthorizationUrl() { - java.lang.Object ref = authorizationUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - authorizationUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The authorization URL to be used for this flow. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS
-     * 
- * - * string authorization_url = 1; - * @return The bytes for authorizationUrl. - */ - public com.google.protobuf.ByteString - getAuthorizationUrlBytes() { - java.lang.Object ref = authorizationUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - authorizationUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The authorization URL to be used for this flow. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS
-     * 
- * - * string authorization_url = 1; - * @param value The authorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setAuthorizationUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - authorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The authorization URL to be used for this flow. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS
-     * 
- * - * string authorization_url = 1; - * @return This builder for chaining. - */ - public Builder clearAuthorizationUrl() { - authorizationUrl_ = getDefaultInstance().getAuthorizationUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The authorization URL to be used for this flow. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS
-     * 
- * - * string authorization_url = 1; - * @param value The bytes for authorizationUrl to set. - * @return This builder for chaining. - */ - public Builder setAuthorizationUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - authorizationUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object refreshUrl_ = ""; - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @param value The refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @return This builder for chaining. - */ - public Builder clearRefreshUrl() { - refreshUrl_ = getDefaultInstance().getRefreshUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @param value The bytes for refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - private com.google.protobuf.MapField - internalGetMutableScopes() { - if (scopes_ == null) { - scopes_ = com.google.protobuf.MapField.newMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - if (!scopes_.isMutable()) { - scopes_ = scopes_.copy(); - } - bitField0_ |= 0x00000004; - onChanged(); - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - public Builder clearScopes() { - bitField0_ = (bitField0_ & ~0x00000004); - internalGetMutableScopes().getMutableMap() - .clear(); - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - public Builder removeScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableScopes().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableScopes() { - bitField0_ |= 0x00000004; - return internalGetMutableScopes().getMutableMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - public Builder putScopes( - java.lang.String key, - java.lang.String value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableScopes().getMutableMap() - .put(key, value); - bitField0_ |= 0x00000004; - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - public Builder putAllScopes( - java.util.Map values) { - internalGetMutableScopes().getMutableMap() - .putAll(values); - bitField0_ |= 0x00000004; - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.ImplicitOAuthFlow) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.ImplicitOAuthFlow) - private static final io.a2a.grpc.ImplicitOAuthFlow DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.ImplicitOAuthFlow(); - } - - public static io.a2a.grpc.ImplicitOAuthFlow getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ImplicitOAuthFlow parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.ImplicitOAuthFlow getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java deleted file mode 100644 index 3b0180dbc..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ImplicitOAuthFlowOrBuilder.java +++ /dev/null @@ -1,115 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ImplicitOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ImplicitOAuthFlow) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The authorization URL to be used for this flow. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS
-   * 
- * - * string authorization_url = 1; - * @return The authorizationUrl. - */ - java.lang.String getAuthorizationUrl(); - /** - *
-   * The authorization URL to be used for this flow. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS
-   * 
- * - * string authorization_url = 1; - * @return The bytes for authorizationUrl. - */ - com.google.protobuf.ByteString - getAuthorizationUrlBytes(); - - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - java.lang.String getRefreshUrl(); - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - com.google.protobuf.ByteString - getRefreshUrlBytes(); - - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - int getScopesCount(); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - boolean containsScopes( - java.lang.String key); - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getScopes(); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - java.util.Map - getScopesMap(); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - java.lang.String getScopesOrThrow( - java.lang.String key); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java deleted file mode 100644 index b80396df7..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequest.java +++ /dev/null @@ -1,948 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:ListTaskPushNotificationConfigRequest]
- * 
- * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigRequest} - */ -@com.google.protobuf.Generated -public final class ListTaskPushNotificationConfigRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTaskPushNotificationConfigRequest) - ListTaskPushNotificationConfigRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "ListTaskPushNotificationConfigRequest"); - } - // Use ListTaskPushNotificationConfigRequest.newBuilder() to construct. - private ListTaskPushNotificationConfigRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private ListTaskPushNotificationConfigRequest() { - tenant_ = ""; - taskId_ = ""; - pageToken_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder.class); - } - - public static final int TENANT_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PAGE_SIZE_FIELD_NUMBER = 2; - private int pageSize_ = 0; - /** - *
-   * The maximum number of configurations to return.
-   * 
- * - * int32 page_size = 2; - * @return The pageSize. - */ - @java.lang.Override - public int getPageSize() { - return pageSize_; - } - - public static final int PAGE_TOKEN_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object pageToken_ = ""; - /** - *
-   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-   * 
- * - * string page_token = 3; - * @return The pageToken. - */ - @java.lang.Override - public java.lang.String getPageToken() { - java.lang.Object ref = pageToken_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - pageToken_ = s; - return s; - } - } - /** - *
-   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-   * 
- * - * string page_token = 3; - * @return The bytes for pageToken. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getPageTokenBytes() { - java.lang.Object ref = pageToken_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - pageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); - } - if (pageSize_ != 0) { - output.writeInt32(2, pageSize_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, pageToken_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); - } - if (pageSize_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(2, pageSize_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, pageToken_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigRequest)) { - return super.equals(obj); - } - io.a2a.grpc.ListTaskPushNotificationConfigRequest other = (io.a2a.grpc.ListTaskPushNotificationConfigRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (getPageSize() - != other.getPageSize()) return false; - if (!getPageToken() - .equals(other.getPageToken())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + PAGE_SIZE_FIELD_NUMBER; - hash = (53 * hash) + getPageSize(); - hash = (37 * hash) + PAGE_TOKEN_FIELD_NUMBER; - hash = (53 * hash) + getPageToken().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:ListTaskPushNotificationConfigRequest]
-   * 
- * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTaskPushNotificationConfigRequest) - io.a2a.grpc.ListTaskPushNotificationConfigRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigRequest.class, io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder.class); - } - - // Construct using io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - taskId_ = ""; - pageSize_ = 0; - pageToken_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return io.a2a.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest build() { - io.a2a.grpc.ListTaskPushNotificationConfigRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest buildPartial() { - io.a2a.grpc.ListTaskPushNotificationConfigRequest result = new io.a2a.grpc.ListTaskPushNotificationConfigRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.taskId_ = taskId_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.pageSize_ = pageSize_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.pageToken_ = pageToken_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigRequest) { - return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigRequest other) { - if (other == io.a2a.grpc.ListTaskPushNotificationConfigRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.getPageSize() != 0) { - setPageSize(other.getPageSize()); - } - if (!other.getPageToken().isEmpty()) { - pageToken_ = other.pageToken_; - bitField0_ |= 0x00000008; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 16: { - pageSize_ = input.readInt32(); - bitField0_ |= 0x00000004; - break; - } // case 16 - case 26: { - pageToken_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000008; - break; - } // case 26 - case 34: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object taskId_ = ""; - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The parent task resource id.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private int pageSize_ ; - /** - *
-     * The maximum number of configurations to return.
-     * 
- * - * int32 page_size = 2; - * @return The pageSize. - */ - @java.lang.Override - public int getPageSize() { - return pageSize_; - } - /** - *
-     * The maximum number of configurations to return.
-     * 
- * - * int32 page_size = 2; - * @param value The pageSize to set. - * @return This builder for chaining. - */ - public Builder setPageSize(int value) { - - pageSize_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The maximum number of configurations to return.
-     * 
- * - * int32 page_size = 2; - * @return This builder for chaining. - */ - public Builder clearPageSize() { - bitField0_ = (bitField0_ & ~0x00000004); - pageSize_ = 0; - onChanged(); - return this; - } - - private java.lang.Object pageToken_ = ""; - /** - *
-     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-     * 
- * - * string page_token = 3; - * @return The pageToken. - */ - public java.lang.String getPageToken() { - java.lang.Object ref = pageToken_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - pageToken_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-     * 
- * - * string page_token = 3; - * @return The bytes for pageToken. - */ - public com.google.protobuf.ByteString - getPageTokenBytes() { - java.lang.Object ref = pageToken_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - pageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-     * 
- * - * string page_token = 3; - * @param value The pageToken to set. - * @return This builder for chaining. - */ - public Builder setPageToken( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - pageToken_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-     * 
- * - * string page_token = 3; - * @return This builder for chaining. - */ - public Builder clearPageToken() { - pageToken_ = getDefaultInstance().getPageToken(); - bitField0_ = (bitField0_ & ~0x00000008); - onChanged(); - return this; - } - /** - *
-     * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-     * 
- * - * string page_token = 3; - * @param value The bytes for pageToken to set. - * @return This builder for chaining. - */ - public Builder setPageTokenBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - pageToken_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTaskPushNotificationConfigRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.ListTaskPushNotificationConfigRequest) - private static final io.a2a.grpc.ListTaskPushNotificationConfigRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigRequest(); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ListTaskPushNotificationConfigRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java deleted file mode 100644 index ba43bb3d7..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigRequestOrBuilder.java +++ /dev/null @@ -1,82 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ListTaskPushNotificationConfigRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTaskPushNotificationConfigRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The parent task resource id.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * The maximum number of configurations to return.
-   * 
- * - * int32 page_size = 2; - * @return The pageSize. - */ - int getPageSize(); - - /** - *
-   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-   * 
- * - * string page_token = 3; - * @return The pageToken. - */ - java.lang.String getPageToken(); - /** - *
-   * A page token received from a previous ListTaskPushNotificationConfigRequest call.
-   * 
- * - * string page_token = 3; - * @return The bytes for pageToken. - */ - com.google.protobuf.ByteString - getPageTokenBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java deleted file mode 100644 index e057230c9..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponse.java +++ /dev/null @@ -1,995 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:ListTaskPushNotificationConfigResponse]
- * Represents a successful response for the `ListTaskPushNotificationConfig`
- * method.
- * 
- * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigResponse} - */ -@com.google.protobuf.Generated -public final class ListTaskPushNotificationConfigResponse extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTaskPushNotificationConfigResponse) - ListTaskPushNotificationConfigResponseOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "ListTaskPushNotificationConfigResponse"); - } - // Use ListTaskPushNotificationConfigResponse.newBuilder() to construct. - private ListTaskPushNotificationConfigResponse(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private ListTaskPushNotificationConfigResponse() { - configs_ = java.util.Collections.emptyList(); - nextPageToken_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder.class); - } - - public static final int CONFIGS_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private java.util.List configs_; - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - @java.lang.Override - public java.util.List getConfigsList() { - return configs_; - } - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - @java.lang.Override - public java.util.List - getConfigsOrBuilderList() { - return configs_; - } - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - @java.lang.Override - public int getConfigsCount() { - return configs_.size(); - } - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) { - return configs_.get(index); - } - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( - int index) { - return configs_.get(index); - } - - public static final int NEXT_PAGE_TOKEN_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object nextPageToken_ = ""; - /** - *
-   * A token, which can be sent as `page_token` to retrieve the next page.
-   * If this field is omitted, there are no subsequent pages.
-   * 
- * - * string next_page_token = 2; - * @return The nextPageToken. - */ - @java.lang.Override - public java.lang.String getNextPageToken() { - java.lang.Object ref = nextPageToken_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - nextPageToken_ = s; - return s; - } - } - /** - *
-   * A token, which can be sent as `page_token` to retrieve the next page.
-   * If this field is omitted, there are no subsequent pages.
-   * 
- * - * string next_page_token = 2; - * @return The bytes for nextPageToken. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getNextPageTokenBytes() { - java.lang.Object ref = nextPageToken_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - nextPageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - for (int i = 0; i < configs_.size(); i++) { - output.writeMessage(1, configs_.get(i)); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(nextPageToken_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, nextPageToken_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - for (int i = 0; i < configs_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, configs_.get(i)); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(nextPageToken_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, nextPageToken_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.ListTaskPushNotificationConfigResponse)) { - return super.equals(obj); - } - io.a2a.grpc.ListTaskPushNotificationConfigResponse other = (io.a2a.grpc.ListTaskPushNotificationConfigResponse) obj; - - if (!getConfigsList() - .equals(other.getConfigsList())) return false; - if (!getNextPageToken() - .equals(other.getNextPageToken())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (getConfigsCount() > 0) { - hash = (37 * hash) + CONFIGS_FIELD_NUMBER; - hash = (53 * hash) + getConfigsList().hashCode(); - } - hash = (37 * hash) + NEXT_PAGE_TOKEN_FIELD_NUMBER; - hash = (53 * hash) + getNextPageToken().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.ListTaskPushNotificationConfigResponse prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:ListTaskPushNotificationConfigResponse]
-   * Represents a successful response for the `ListTaskPushNotificationConfig`
-   * method.
-   * 
- * - * Protobuf type {@code a2a.v1.ListTaskPushNotificationConfigResponse} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTaskPushNotificationConfigResponse) - io.a2a.grpc.ListTaskPushNotificationConfigResponseOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTaskPushNotificationConfigResponse.class, io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder.class); - } - - // Construct using io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - if (configsBuilder_ == null) { - configs_ = java.util.Collections.emptyList(); - } else { - configs_ = null; - configsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000001); - nextPageToken_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTaskPushNotificationConfigResponse_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse getDefaultInstanceForType() { - return io.a2a.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse build() { - io.a2a.grpc.ListTaskPushNotificationConfigResponse result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse buildPartial() { - io.a2a.grpc.ListTaskPushNotificationConfigResponse result = new io.a2a.grpc.ListTaskPushNotificationConfigResponse(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.ListTaskPushNotificationConfigResponse result) { - if (configsBuilder_ == null) { - if (((bitField0_ & 0x00000001) != 0)) { - configs_ = java.util.Collections.unmodifiableList(configs_); - bitField0_ = (bitField0_ & ~0x00000001); - } - result.configs_ = configs_; - } else { - result.configs_ = configsBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.ListTaskPushNotificationConfigResponse result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000002) != 0)) { - result.nextPageToken_ = nextPageToken_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ListTaskPushNotificationConfigResponse) { - return mergeFrom((io.a2a.grpc.ListTaskPushNotificationConfigResponse)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.ListTaskPushNotificationConfigResponse other) { - if (other == io.a2a.grpc.ListTaskPushNotificationConfigResponse.getDefaultInstance()) return this; - if (configsBuilder_ == null) { - if (!other.configs_.isEmpty()) { - if (configs_.isEmpty()) { - configs_ = other.configs_; - bitField0_ = (bitField0_ & ~0x00000001); - } else { - ensureConfigsIsMutable(); - configs_.addAll(other.configs_); - } - onChanged(); - } - } else { - if (!other.configs_.isEmpty()) { - if (configsBuilder_.isEmpty()) { - configsBuilder_.dispose(); - configsBuilder_ = null; - configs_ = other.configs_; - bitField0_ = (bitField0_ & ~0x00000001); - configsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetConfigsFieldBuilder() : null; - } else { - configsBuilder_.addAllMessages(other.configs_); - } - } - } - if (!other.getNextPageToken().isEmpty()) { - nextPageToken_ = other.nextPageToken_; - bitField0_ |= 0x00000002; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - io.a2a.grpc.TaskPushNotificationConfig m = - input.readMessage( - io.a2a.grpc.TaskPushNotificationConfig.parser(), - extensionRegistry); - if (configsBuilder_ == null) { - ensureConfigsIsMutable(); - configs_.add(m); - } else { - configsBuilder_.addMessage(m); - } - break; - } // case 10 - case 18: { - nextPageToken_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.util.List configs_ = - java.util.Collections.emptyList(); - private void ensureConfigsIsMutable() { - if (!((bitField0_ & 0x00000001) != 0)) { - configs_ = new java.util.ArrayList(configs_); - bitField0_ |= 0x00000001; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> configsBuilder_; - - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public java.util.List getConfigsList() { - if (configsBuilder_ == null) { - return java.util.Collections.unmodifiableList(configs_); - } else { - return configsBuilder_.getMessageList(); - } - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public int getConfigsCount() { - if (configsBuilder_ == null) { - return configs_.size(); - } else { - return configsBuilder_.getCount(); - } - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index) { - if (configsBuilder_ == null) { - return configs_.get(index); - } else { - return configsBuilder_.getMessage(index); - } - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder setConfigs( - int index, io.a2a.grpc.TaskPushNotificationConfig value) { - if (configsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureConfigsIsMutable(); - configs_.set(index, value); - onChanged(); - } else { - configsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder setConfigs( - int index, io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { - if (configsBuilder_ == null) { - ensureConfigsIsMutable(); - configs_.set(index, builderForValue.build()); - onChanged(); - } else { - configsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder addConfigs(io.a2a.grpc.TaskPushNotificationConfig value) { - if (configsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureConfigsIsMutable(); - configs_.add(value); - onChanged(); - } else { - configsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder addConfigs( - int index, io.a2a.grpc.TaskPushNotificationConfig value) { - if (configsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureConfigsIsMutable(); - configs_.add(index, value); - onChanged(); - } else { - configsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder addConfigs( - io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { - if (configsBuilder_ == null) { - ensureConfigsIsMutable(); - configs_.add(builderForValue.build()); - onChanged(); - } else { - configsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder addConfigs( - int index, io.a2a.grpc.TaskPushNotificationConfig.Builder builderForValue) { - if (configsBuilder_ == null) { - ensureConfigsIsMutable(); - configs_.add(index, builderForValue.build()); - onChanged(); - } else { - configsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder addAllConfigs( - java.lang.Iterable values) { - if (configsBuilder_ == null) { - ensureConfigsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, configs_); - onChanged(); - } else { - configsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder clearConfigs() { - if (configsBuilder_ == null) { - configs_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - } else { - configsBuilder_.clear(); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public Builder removeConfigs(int index) { - if (configsBuilder_ == null) { - ensureConfigsIsMutable(); - configs_.remove(index); - onChanged(); - } else { - configsBuilder_.remove(index); - } - return this; - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public io.a2a.grpc.TaskPushNotificationConfig.Builder getConfigsBuilder( - int index) { - return internalGetConfigsFieldBuilder().getBuilder(index); - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( - int index) { - if (configsBuilder_ == null) { - return configs_.get(index); } else { - return configsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public java.util.List - getConfigsOrBuilderList() { - if (configsBuilder_ != null) { - return configsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(configs_); - } - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder() { - return internalGetConfigsFieldBuilder().addBuilder( - io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()); - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public io.a2a.grpc.TaskPushNotificationConfig.Builder addConfigsBuilder( - int index) { - return internalGetConfigsFieldBuilder().addBuilder( - index, io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()); - } - /** - *
-     * The list of push notification configurations.
-     * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - public java.util.List - getConfigsBuilderList() { - return internalGetConfigsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder> - internalGetConfigsFieldBuilder() { - if (configsBuilder_ == null) { - configsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.TaskPushNotificationConfig, io.a2a.grpc.TaskPushNotificationConfig.Builder, io.a2a.grpc.TaskPushNotificationConfigOrBuilder>( - configs_, - ((bitField0_ & 0x00000001) != 0), - getParentForChildren(), - isClean()); - configs_ = null; - } - return configsBuilder_; - } - - private java.lang.Object nextPageToken_ = ""; - /** - *
-     * A token, which can be sent as `page_token` to retrieve the next page.
-     * If this field is omitted, there are no subsequent pages.
-     * 
- * - * string next_page_token = 2; - * @return The nextPageToken. - */ - public java.lang.String getNextPageToken() { - java.lang.Object ref = nextPageToken_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - nextPageToken_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A token, which can be sent as `page_token` to retrieve the next page.
-     * If this field is omitted, there are no subsequent pages.
-     * 
- * - * string next_page_token = 2; - * @return The bytes for nextPageToken. - */ - public com.google.protobuf.ByteString - getNextPageTokenBytes() { - java.lang.Object ref = nextPageToken_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - nextPageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A token, which can be sent as `page_token` to retrieve the next page.
-     * If this field is omitted, there are no subsequent pages.
-     * 
- * - * string next_page_token = 2; - * @param value The nextPageToken to set. - * @return This builder for chaining. - */ - public Builder setNextPageToken( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - nextPageToken_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * A token, which can be sent as `page_token` to retrieve the next page.
-     * If this field is omitted, there are no subsequent pages.
-     * 
- * - * string next_page_token = 2; - * @return This builder for chaining. - */ - public Builder clearNextPageToken() { - nextPageToken_ = getDefaultInstance().getNextPageToken(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * A token, which can be sent as `page_token` to retrieve the next page.
-     * If this field is omitted, there are no subsequent pages.
-     * 
- * - * string next_page_token = 2; - * @param value The bytes for nextPageToken to set. - * @return This builder for chaining. - */ - public Builder setNextPageTokenBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - nextPageToken_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTaskPushNotificationConfigResponse) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.ListTaskPushNotificationConfigResponse) - private static final io.a2a.grpc.ListTaskPushNotificationConfigResponse DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.ListTaskPushNotificationConfigResponse(); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ListTaskPushNotificationConfigResponse parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.ListTaskPushNotificationConfigResponse getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java deleted file mode 100644 index a68796c49..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTaskPushNotificationConfigResponseOrBuilder.java +++ /dev/null @@ -1,78 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ListTaskPushNotificationConfigResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTaskPushNotificationConfigResponse) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - java.util.List - getConfigsList(); - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - io.a2a.grpc.TaskPushNotificationConfig getConfigs(int index); - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - int getConfigsCount(); - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - java.util.List - getConfigsOrBuilderList(); - /** - *
-   * The list of push notification configurations.
-   * 
- * - * repeated .a2a.v1.TaskPushNotificationConfig configs = 1; - */ - io.a2a.grpc.TaskPushNotificationConfigOrBuilder getConfigsOrBuilder( - int index); - - /** - *
-   * A token, which can be sent as `page_token` to retrieve the next page.
-   * If this field is omitted, there are no subsequent pages.
-   * 
- * - * string next_page_token = 2; - * @return The nextPageToken. - */ - java.lang.String getNextPageToken(); - /** - *
-   * A token, which can be sent as `page_token` to retrieve the next page.
-   * If this field is omitted, there are no subsequent pages.
-   * 
- * - * string next_page_token = 2; - * @return The bytes for nextPageToken. - */ - com.google.protobuf.ByteString - getNextPageTokenBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java deleted file mode 100644 index c2645afcc..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequest.java +++ /dev/null @@ -1,1590 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:ListTasksRequest]
- * Parameters for listing tasks with optional filtering criteria.
- * 
- * - * Protobuf type {@code a2a.v1.ListTasksRequest} - */ -@com.google.protobuf.Generated -public final class ListTasksRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTasksRequest) - ListTasksRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "ListTasksRequest"); - } - // Use ListTasksRequest.newBuilder() to construct. - private ListTasksRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private ListTasksRequest() { - tenant_ = ""; - contextId_ = ""; - status_ = 0; - pageToken_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTasksRequest.class, io.a2a.grpc.ListTasksRequest.Builder.class); - } - - private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 9; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 9; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 9; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONTEXT_ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object contextId_ = ""; - /** - *
-   * Filter tasks by context ID to get tasks from a specific conversation or session.
-   * 
- * - * string context_id = 1; - * @return The contextId. - */ - @java.lang.Override - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } - } - /** - *
-   * Filter tasks by context ID to get tasks from a specific conversation or session.
-   * 
- * - * string context_id = 1; - * @return The bytes for contextId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int STATUS_FIELD_NUMBER = 2; - private int status_ = 0; - /** - *
-   * Filter tasks by their current status state.
-   * 
- * - * .a2a.v1.TaskState status = 2; - * @return The enum numeric value on the wire for status. - */ - @java.lang.Override public int getStatusValue() { - return status_; - } - /** - *
-   * Filter tasks by their current status state.
-   * 
- * - * .a2a.v1.TaskState status = 2; - * @return The status. - */ - @java.lang.Override public io.a2a.grpc.TaskState getStatus() { - io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(status_); - return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result; - } - - public static final int PAGE_SIZE_FIELD_NUMBER = 3; - private int pageSize_ = 0; - /** - *
-   * Maximum number of tasks to return. Must be between 1 and 100.
-   * Defaults to 50 if not specified.
-   * 
- * - * optional int32 page_size = 3; - * @return Whether the pageSize field is set. - */ - @java.lang.Override - public boolean hasPageSize() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * Maximum number of tasks to return. Must be between 1 and 100.
-   * Defaults to 50 if not specified.
-   * 
- * - * optional int32 page_size = 3; - * @return The pageSize. - */ - @java.lang.Override - public int getPageSize() { - return pageSize_; - } - - public static final int PAGE_TOKEN_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object pageToken_ = ""; - /** - *
-   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-   * 
- * - * string page_token = 4; - * @return The pageToken. - */ - @java.lang.Override - public java.lang.String getPageToken() { - java.lang.Object ref = pageToken_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - pageToken_ = s; - return s; - } - } - /** - *
-   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-   * 
- * - * string page_token = 4; - * @return The bytes for pageToken. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getPageTokenBytes() { - java.lang.Object ref = pageToken_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - pageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int HISTORY_LENGTH_FIELD_NUMBER = 5; - private int historyLength_ = 0; - /** - *
-   * The maximum number of messages to include in each task's history.
-   * 
- * - * optional int32 history_length = 5; - * @return Whether the historyLength field is set. - */ - @java.lang.Override - public boolean hasHistoryLength() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * The maximum number of messages to include in each task's history.
-   * 
- * - * optional int32 history_length = 5; - * @return The historyLength. - */ - @java.lang.Override - public int getHistoryLength() { - return historyLength_; - } - - public static final int STATUS_TIMESTAMP_AFTER_FIELD_NUMBER = 6; - private com.google.protobuf.Timestamp statusTimestampAfter_; - /** - *
-   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-   * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - * @return Whether the statusTimestampAfter field is set. - */ - @java.lang.Override - public boolean hasStatusTimestampAfter() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-   * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - * @return The statusTimestampAfter. - */ - @java.lang.Override - public com.google.protobuf.Timestamp getStatusTimestampAfter() { - return statusTimestampAfter_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; - } - /** - *
-   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-   * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - @java.lang.Override - public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() { - return statusTimestampAfter_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; - } - - public static final int INCLUDE_ARTIFACTS_FIELD_NUMBER = 7; - private boolean includeArtifacts_ = false; - /** - *
-   * Whether to include artifacts in the returned tasks.
-   * Defaults to false to reduce payload size.
-   * 
- * - * optional bool include_artifacts = 7; - * @return Whether the includeArtifacts field is set. - */ - @java.lang.Override - public boolean hasIncludeArtifacts() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-   * Whether to include artifacts in the returned tasks.
-   * Defaults to false to reduce payload size.
-   * 
- * - * optional bool include_artifacts = 7; - * @return The includeArtifacts. - */ - @java.lang.Override - public boolean getIncludeArtifacts() { - return includeArtifacts_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, contextId_); - } - if (status_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { - output.writeEnum(2, status_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeInt32(3, pageSize_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, pageToken_); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeInt32(5, historyLength_); - } - if (((bitField0_ & 0x00000004) != 0)) { - output.writeMessage(6, getStatusTimestampAfter()); - } - if (((bitField0_ & 0x00000008) != 0)) { - output.writeBool(7, includeArtifacts_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 9, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, contextId_); - } - if (status_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { - size += com.google.protobuf.CodedOutputStream - .computeEnumSize(2, status_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, pageSize_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(pageToken_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, pageToken_); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(5, historyLength_); - } - if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getStatusTimestampAfter()); - } - if (((bitField0_ & 0x00000008) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(7, includeArtifacts_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(9, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.ListTasksRequest)) { - return super.equals(obj); - } - io.a2a.grpc.ListTasksRequest other = (io.a2a.grpc.ListTasksRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getContextId() - .equals(other.getContextId())) return false; - if (status_ != other.status_) return false; - if (hasPageSize() != other.hasPageSize()) return false; - if (hasPageSize()) { - if (getPageSize() - != other.getPageSize()) return false; - } - if (!getPageToken() - .equals(other.getPageToken())) return false; - if (hasHistoryLength() != other.hasHistoryLength()) return false; - if (hasHistoryLength()) { - if (getHistoryLength() - != other.getHistoryLength()) return false; - } - if (hasStatusTimestampAfter() != other.hasStatusTimestampAfter()) return false; - if (hasStatusTimestampAfter()) { - if (!getStatusTimestampAfter() - .equals(other.getStatusTimestampAfter())) return false; - } - if (hasIncludeArtifacts() != other.hasIncludeArtifacts()) return false; - if (hasIncludeArtifacts()) { - if (getIncludeArtifacts() - != other.getIncludeArtifacts()) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; - hash = (53 * hash) + getContextId().hashCode(); - hash = (37 * hash) + STATUS_FIELD_NUMBER; - hash = (53 * hash) + status_; - if (hasPageSize()) { - hash = (37 * hash) + PAGE_SIZE_FIELD_NUMBER; - hash = (53 * hash) + getPageSize(); - } - hash = (37 * hash) + PAGE_TOKEN_FIELD_NUMBER; - hash = (53 * hash) + getPageToken().hashCode(); - if (hasHistoryLength()) { - hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; - hash = (53 * hash) + getHistoryLength(); - } - if (hasStatusTimestampAfter()) { - hash = (37 * hash) + STATUS_TIMESTAMP_AFTER_FIELD_NUMBER; - hash = (53 * hash) + getStatusTimestampAfter().hashCode(); - } - if (hasIncludeArtifacts()) { - hash = (37 * hash) + INCLUDE_ARTIFACTS_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getIncludeArtifacts()); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.ListTasksRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTasksRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTasksRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTasksRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTasksRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTasksRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTasksRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTasksRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.ListTasksRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.ListTasksRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.ListTasksRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTasksRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.ListTasksRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:ListTasksRequest]
-   * Parameters for listing tasks with optional filtering criteria.
-   * 
- * - * Protobuf type {@code a2a.v1.ListTasksRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTasksRequest) - io.a2a.grpc.ListTasksRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTasksRequest.class, io.a2a.grpc.ListTasksRequest.Builder.class); - } - - // Construct using io.a2a.grpc.ListTasksRequest.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetStatusTimestampAfterFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - contextId_ = ""; - status_ = 0; - pageSize_ = 0; - pageToken_ = ""; - historyLength_ = 0; - statusTimestampAfter_ = null; - if (statusTimestampAfterBuilder_ != null) { - statusTimestampAfterBuilder_.dispose(); - statusTimestampAfterBuilder_ = null; - } - includeArtifacts_ = false; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.ListTasksRequest getDefaultInstanceForType() { - return io.a2a.grpc.ListTasksRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.ListTasksRequest build() { - io.a2a.grpc.ListTasksRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.ListTasksRequest buildPartial() { - io.a2a.grpc.ListTasksRequest result = new io.a2a.grpc.ListTasksRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.ListTasksRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.contextId_ = contextId_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.status_ = status_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { - result.pageSize_ = pageSize_; - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000010) != 0)) { - result.pageToken_ = pageToken_; - } - if (((from_bitField0_ & 0x00000020) != 0)) { - result.historyLength_ = historyLength_; - to_bitField0_ |= 0x00000002; - } - if (((from_bitField0_ & 0x00000040) != 0)) { - result.statusTimestampAfter_ = statusTimestampAfterBuilder_ == null - ? statusTimestampAfter_ - : statusTimestampAfterBuilder_.build(); - to_bitField0_ |= 0x00000004; - } - if (((from_bitField0_ & 0x00000080) != 0)) { - result.includeArtifacts_ = includeArtifacts_; - to_bitField0_ |= 0x00000008; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ListTasksRequest) { - return mergeFrom((io.a2a.grpc.ListTasksRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.ListTasksRequest other) { - if (other == io.a2a.grpc.ListTasksRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getContextId().isEmpty()) { - contextId_ = other.contextId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.status_ != 0) { - setStatusValue(other.getStatusValue()); - } - if (other.hasPageSize()) { - setPageSize(other.getPageSize()); - } - if (!other.getPageToken().isEmpty()) { - pageToken_ = other.pageToken_; - bitField0_ |= 0x00000010; - onChanged(); - } - if (other.hasHistoryLength()) { - setHistoryLength(other.getHistoryLength()); - } - if (other.hasStatusTimestampAfter()) { - mergeStatusTimestampAfter(other.getStatusTimestampAfter()); - } - if (other.hasIncludeArtifacts()) { - setIncludeArtifacts(other.getIncludeArtifacts()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - contextId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 16: { - status_ = input.readEnum(); - bitField0_ |= 0x00000004; - break; - } // case 16 - case 24: { - pageSize_ = input.readInt32(); - bitField0_ |= 0x00000008; - break; - } // case 24 - case 34: { - pageToken_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000010; - break; - } // case 34 - case 40: { - historyLength_ = input.readInt32(); - bitField0_ |= 0x00000020; - break; - } // case 40 - case 50: { - input.readMessage( - internalGetStatusTimestampAfterFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000040; - break; - } // case 50 - case 56: { - includeArtifacts_ = input.readBool(); - bitField0_ |= 0x00000080; - break; - } // case 56 - case 74: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 74 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 9; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 9; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 9; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 9; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 9; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object contextId_ = ""; - /** - *
-     * Filter tasks by context ID to get tasks from a specific conversation or session.
-     * 
- * - * string context_id = 1; - * @return The contextId. - */ - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Filter tasks by context ID to get tasks from a specific conversation or session.
-     * 
- * - * string context_id = 1; - * @return The bytes for contextId. - */ - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Filter tasks by context ID to get tasks from a specific conversation or session.
-     * 
- * - * string context_id = 1; - * @param value The contextId to set. - * @return This builder for chaining. - */ - public Builder setContextId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Filter tasks by context ID to get tasks from a specific conversation or session.
-     * 
- * - * string context_id = 1; - * @return This builder for chaining. - */ - public Builder clearContextId() { - contextId_ = getDefaultInstance().getContextId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * Filter tasks by context ID to get tasks from a specific conversation or session.
-     * 
- * - * string context_id = 1; - * @param value The bytes for contextId to set. - * @return This builder for chaining. - */ - public Builder setContextIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private int status_ = 0; - /** - *
-     * Filter tasks by their current status state.
-     * 
- * - * .a2a.v1.TaskState status = 2; - * @return The enum numeric value on the wire for status. - */ - @java.lang.Override public int getStatusValue() { - return status_; - } - /** - *
-     * Filter tasks by their current status state.
-     * 
- * - * .a2a.v1.TaskState status = 2; - * @param value The enum numeric value on the wire for status to set. - * @return This builder for chaining. - */ - public Builder setStatusValue(int value) { - status_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * Filter tasks by their current status state.
-     * 
- * - * .a2a.v1.TaskState status = 2; - * @return The status. - */ - @java.lang.Override - public io.a2a.grpc.TaskState getStatus() { - io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(status_); - return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result; - } - /** - *
-     * Filter tasks by their current status state.
-     * 
- * - * .a2a.v1.TaskState status = 2; - * @param value The status to set. - * @return This builder for chaining. - */ - public Builder setStatus(io.a2a.grpc.TaskState value) { - if (value == null) { throw new NullPointerException(); } - bitField0_ |= 0x00000004; - status_ = value.getNumber(); - onChanged(); - return this; - } - /** - *
-     * Filter tasks by their current status state.
-     * 
- * - * .a2a.v1.TaskState status = 2; - * @return This builder for chaining. - */ - public Builder clearStatus() { - bitField0_ = (bitField0_ & ~0x00000004); - status_ = 0; - onChanged(); - return this; - } - - private int pageSize_ ; - /** - *
-     * Maximum number of tasks to return. Must be between 1 and 100.
-     * Defaults to 50 if not specified.
-     * 
- * - * optional int32 page_size = 3; - * @return Whether the pageSize field is set. - */ - @java.lang.Override - public boolean hasPageSize() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * Maximum number of tasks to return. Must be between 1 and 100.
-     * Defaults to 50 if not specified.
-     * 
- * - * optional int32 page_size = 3; - * @return The pageSize. - */ - @java.lang.Override - public int getPageSize() { - return pageSize_; - } - /** - *
-     * Maximum number of tasks to return. Must be between 1 and 100.
-     * Defaults to 50 if not specified.
-     * 
- * - * optional int32 page_size = 3; - * @param value The pageSize to set. - * @return This builder for chaining. - */ - public Builder setPageSize(int value) { - - pageSize_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Maximum number of tasks to return. Must be between 1 and 100.
-     * Defaults to 50 if not specified.
-     * 
- * - * optional int32 page_size = 3; - * @return This builder for chaining. - */ - public Builder clearPageSize() { - bitField0_ = (bitField0_ & ~0x00000008); - pageSize_ = 0; - onChanged(); - return this; - } - - private java.lang.Object pageToken_ = ""; - /** - *
-     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-     * 
- * - * string page_token = 4; - * @return The pageToken. - */ - public java.lang.String getPageToken() { - java.lang.Object ref = pageToken_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - pageToken_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-     * 
- * - * string page_token = 4; - * @return The bytes for pageToken. - */ - public com.google.protobuf.ByteString - getPageTokenBytes() { - java.lang.Object ref = pageToken_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - pageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-     * 
- * - * string page_token = 4; - * @param value The pageToken to set. - * @return This builder for chaining. - */ - public Builder setPageToken( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - pageToken_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-     * 
- * - * string page_token = 4; - * @return This builder for chaining. - */ - public Builder clearPageToken() { - pageToken_ = getDefaultInstance().getPageToken(); - bitField0_ = (bitField0_ & ~0x00000010); - onChanged(); - return this; - } - /** - *
-     * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-     * 
- * - * string page_token = 4; - * @param value The bytes for pageToken to set. - * @return This builder for chaining. - */ - public Builder setPageTokenBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - pageToken_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - - private int historyLength_ ; - /** - *
-     * The maximum number of messages to include in each task's history.
-     * 
- * - * optional int32 history_length = 5; - * @return Whether the historyLength field is set. - */ - @java.lang.Override - public boolean hasHistoryLength() { - return ((bitField0_ & 0x00000020) != 0); - } - /** - *
-     * The maximum number of messages to include in each task's history.
-     * 
- * - * optional int32 history_length = 5; - * @return The historyLength. - */ - @java.lang.Override - public int getHistoryLength() { - return historyLength_; - } - /** - *
-     * The maximum number of messages to include in each task's history.
-     * 
- * - * optional int32 history_length = 5; - * @param value The historyLength to set. - * @return This builder for chaining. - */ - public Builder setHistoryLength(int value) { - - historyLength_ = value; - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * The maximum number of messages to include in each task's history.
-     * 
- * - * optional int32 history_length = 5; - * @return This builder for chaining. - */ - public Builder clearHistoryLength() { - bitField0_ = (bitField0_ & ~0x00000020); - historyLength_ = 0; - onChanged(); - return this; - } - - private com.google.protobuf.Timestamp statusTimestampAfter_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> statusTimestampAfterBuilder_; - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - * @return Whether the statusTimestampAfter field is set. - */ - public boolean hasStatusTimestampAfter() { - return ((bitField0_ & 0x00000040) != 0); - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - * @return The statusTimestampAfter. - */ - public com.google.protobuf.Timestamp getStatusTimestampAfter() { - if (statusTimestampAfterBuilder_ == null) { - return statusTimestampAfter_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; - } else { - return statusTimestampAfterBuilder_.getMessage(); - } - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - public Builder setStatusTimestampAfter(com.google.protobuf.Timestamp value) { - if (statusTimestampAfterBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - statusTimestampAfter_ = value; - } else { - statusTimestampAfterBuilder_.setMessage(value); - } - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - public Builder setStatusTimestampAfter( - com.google.protobuf.Timestamp.Builder builderForValue) { - if (statusTimestampAfterBuilder_ == null) { - statusTimestampAfter_ = builderForValue.build(); - } else { - statusTimestampAfterBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - public Builder mergeStatusTimestampAfter(com.google.protobuf.Timestamp value) { - if (statusTimestampAfterBuilder_ == null) { - if (((bitField0_ & 0x00000040) != 0) && - statusTimestampAfter_ != null && - statusTimestampAfter_ != com.google.protobuf.Timestamp.getDefaultInstance()) { - getStatusTimestampAfterBuilder().mergeFrom(value); - } else { - statusTimestampAfter_ = value; - } - } else { - statusTimestampAfterBuilder_.mergeFrom(value); - } - if (statusTimestampAfter_ != null) { - bitField0_ |= 0x00000040; - onChanged(); - } - return this; - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - public Builder clearStatusTimestampAfter() { - bitField0_ = (bitField0_ & ~0x00000040); - statusTimestampAfter_ = null; - if (statusTimestampAfterBuilder_ != null) { - statusTimestampAfterBuilder_.dispose(); - statusTimestampAfterBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - public com.google.protobuf.Timestamp.Builder getStatusTimestampAfterBuilder() { - bitField0_ |= 0x00000040; - onChanged(); - return internalGetStatusTimestampAfterFieldBuilder().getBuilder(); - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - public com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder() { - if (statusTimestampAfterBuilder_ != null) { - return statusTimestampAfterBuilder_.getMessageOrBuilder(); - } else { - return statusTimestampAfter_ == null ? - com.google.protobuf.Timestamp.getDefaultInstance() : statusTimestampAfter_; - } - } - /** - *
-     * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-     * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-     * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> - internalGetStatusTimestampAfterFieldBuilder() { - if (statusTimestampAfterBuilder_ == null) { - statusTimestampAfterBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>( - getStatusTimestampAfter(), - getParentForChildren(), - isClean()); - statusTimestampAfter_ = null; - } - return statusTimestampAfterBuilder_; - } - - private boolean includeArtifacts_ ; - /** - *
-     * Whether to include artifacts in the returned tasks.
-     * Defaults to false to reduce payload size.
-     * 
- * - * optional bool include_artifacts = 7; - * @return Whether the includeArtifacts field is set. - */ - @java.lang.Override - public boolean hasIncludeArtifacts() { - return ((bitField0_ & 0x00000080) != 0); - } - /** - *
-     * Whether to include artifacts in the returned tasks.
-     * Defaults to false to reduce payload size.
-     * 
- * - * optional bool include_artifacts = 7; - * @return The includeArtifacts. - */ - @java.lang.Override - public boolean getIncludeArtifacts() { - return includeArtifacts_; - } - /** - *
-     * Whether to include artifacts in the returned tasks.
-     * Defaults to false to reduce payload size.
-     * 
- * - * optional bool include_artifacts = 7; - * @param value The includeArtifacts to set. - * @return This builder for chaining. - */ - public Builder setIncludeArtifacts(boolean value) { - - includeArtifacts_ = value; - bitField0_ |= 0x00000080; - onChanged(); - return this; - } - /** - *
-     * Whether to include artifacts in the returned tasks.
-     * Defaults to false to reduce payload size.
-     * 
- * - * optional bool include_artifacts = 7; - * @return This builder for chaining. - */ - public Builder clearIncludeArtifacts() { - bitField0_ = (bitField0_ & ~0x00000080); - includeArtifacts_ = false; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTasksRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.ListTasksRequest) - private static final io.a2a.grpc.ListTasksRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.ListTasksRequest(); - } - - public static io.a2a.grpc.ListTasksRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ListTasksRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.ListTasksRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java deleted file mode 100644 index 410485d50..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksRequestOrBuilder.java +++ /dev/null @@ -1,182 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ListTasksRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTasksRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 9; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 9; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * Filter tasks by context ID to get tasks from a specific conversation or session.
-   * 
- * - * string context_id = 1; - * @return The contextId. - */ - java.lang.String getContextId(); - /** - *
-   * Filter tasks by context ID to get tasks from a specific conversation or session.
-   * 
- * - * string context_id = 1; - * @return The bytes for contextId. - */ - com.google.protobuf.ByteString - getContextIdBytes(); - - /** - *
-   * Filter tasks by their current status state.
-   * 
- * - * .a2a.v1.TaskState status = 2; - * @return The enum numeric value on the wire for status. - */ - int getStatusValue(); - /** - *
-   * Filter tasks by their current status state.
-   * 
- * - * .a2a.v1.TaskState status = 2; - * @return The status. - */ - io.a2a.grpc.TaskState getStatus(); - - /** - *
-   * Maximum number of tasks to return. Must be between 1 and 100.
-   * Defaults to 50 if not specified.
-   * 
- * - * optional int32 page_size = 3; - * @return Whether the pageSize field is set. - */ - boolean hasPageSize(); - /** - *
-   * Maximum number of tasks to return. Must be between 1 and 100.
-   * Defaults to 50 if not specified.
-   * 
- * - * optional int32 page_size = 3; - * @return The pageSize. - */ - int getPageSize(); - - /** - *
-   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-   * 
- * - * string page_token = 4; - * @return The pageToken. - */ - java.lang.String getPageToken(); - /** - *
-   * Token for pagination. Use the next_page_token from a previous ListTasksResponse.
-   * 
- * - * string page_token = 4; - * @return The bytes for pageToken. - */ - com.google.protobuf.ByteString - getPageTokenBytes(); - - /** - *
-   * The maximum number of messages to include in each task's history.
-   * 
- * - * optional int32 history_length = 5; - * @return Whether the historyLength field is set. - */ - boolean hasHistoryLength(); - /** - *
-   * The maximum number of messages to include in each task's history.
-   * 
- * - * optional int32 history_length = 5; - * @return The historyLength. - */ - int getHistoryLength(); - - /** - *
-   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-   * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - * @return Whether the statusTimestampAfter field is set. - */ - boolean hasStatusTimestampAfter(); - /** - *
-   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-   * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - * @return The statusTimestampAfter. - */ - com.google.protobuf.Timestamp getStatusTimestampAfter(); - /** - *
-   * Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z").
-   * Only tasks with a status timestamp time greater than or equal to this value will be returned.
-   * 
- * - * .google.protobuf.Timestamp status_timestamp_after = 6; - */ - com.google.protobuf.TimestampOrBuilder getStatusTimestampAfterOrBuilder(); - - /** - *
-   * Whether to include artifacts in the returned tasks.
-   * Defaults to false to reduce payload size.
-   * 
- * - * optional bool include_artifacts = 7; - * @return Whether the includeArtifacts field is set. - */ - boolean hasIncludeArtifacts(); - /** - *
-   * Whether to include artifacts in the returned tasks.
-   * Defaults to false to reduce payload size.
-   * 
- * - * optional bool include_artifacts = 7; - * @return The includeArtifacts. - */ - boolean getIncludeArtifacts(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java deleted file mode 100644 index 1c0078076..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponse.java +++ /dev/null @@ -1,1150 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:ListTasksResponse]
- * Result object for tasks/list method containing an array of tasks and pagination information.
- * 
- * - * Protobuf type {@code a2a.v1.ListTasksResponse} - */ -@com.google.protobuf.Generated -public final class ListTasksResponse extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.ListTasksResponse) - ListTasksResponseOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "ListTasksResponse"); - } - // Use ListTasksResponse.newBuilder() to construct. - private ListTasksResponse(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private ListTasksResponse() { - tasks_ = java.util.Collections.emptyList(); - nextPageToken_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTasksResponse.class, io.a2a.grpc.ListTasksResponse.Builder.class); - } - - public static final int TASKS_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private java.util.List tasks_; - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List getTasksList() { - return tasks_; - } - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List - getTasksOrBuilderList() { - return tasks_; - } - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public int getTasksCount() { - return tasks_.size(); - } - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.Task getTasks(int index) { - return tasks_.get(index); - } - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( - int index) { - return tasks_.get(index); - } - - public static final int NEXT_PAGE_TOKEN_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object nextPageToken_ = ""; - /** - *
-   * Token for retrieving the next page. Empty string if no more results.
-   * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The nextPageToken. - */ - @java.lang.Override - public java.lang.String getNextPageToken() { - java.lang.Object ref = nextPageToken_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - nextPageToken_ = s; - return s; - } - } - /** - *
-   * Token for retrieving the next page. Empty string if no more results.
-   * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for nextPageToken. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getNextPageTokenBytes() { - java.lang.Object ref = nextPageToken_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - nextPageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PAGE_SIZE_FIELD_NUMBER = 3; - private int pageSize_ = 0; - /** - *
-   * The size of page requested.
-   * 
- * - * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The pageSize. - */ - @java.lang.Override - public int getPageSize() { - return pageSize_; - } - - public static final int TOTAL_SIZE_FIELD_NUMBER = 4; - private int totalSize_ = 0; - /** - *
-   * Total number of tasks available (before pagination).
-   * 
- * - * int32 total_size = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The totalSize. - */ - @java.lang.Override - public int getTotalSize() { - return totalSize_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - for (int i = 0; i < tasks_.size(); i++) { - output.writeMessage(1, tasks_.get(i)); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(nextPageToken_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, nextPageToken_); - } - if (pageSize_ != 0) { - output.writeInt32(3, pageSize_); - } - if (totalSize_ != 0) { - output.writeInt32(4, totalSize_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - for (int i = 0; i < tasks_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, tasks_.get(i)); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(nextPageToken_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, nextPageToken_); - } - if (pageSize_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, pageSize_); - } - if (totalSize_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(4, totalSize_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.ListTasksResponse)) { - return super.equals(obj); - } - io.a2a.grpc.ListTasksResponse other = (io.a2a.grpc.ListTasksResponse) obj; - - if (!getTasksList() - .equals(other.getTasksList())) return false; - if (!getNextPageToken() - .equals(other.getNextPageToken())) return false; - if (getPageSize() - != other.getPageSize()) return false; - if (getTotalSize() - != other.getTotalSize()) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (getTasksCount() > 0) { - hash = (37 * hash) + TASKS_FIELD_NUMBER; - hash = (53 * hash) + getTasksList().hashCode(); - } - hash = (37 * hash) + NEXT_PAGE_TOKEN_FIELD_NUMBER; - hash = (53 * hash) + getNextPageToken().hashCode(); - hash = (37 * hash) + PAGE_SIZE_FIELD_NUMBER; - hash = (53 * hash) + getPageSize(); - hash = (37 * hash) + TOTAL_SIZE_FIELD_NUMBER; - hash = (53 * hash) + getTotalSize(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.ListTasksResponse parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTasksResponse parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTasksResponse parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTasksResponse parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTasksResponse parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.ListTasksResponse parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.ListTasksResponse parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTasksResponse parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.ListTasksResponse parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.ListTasksResponse parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.ListTasksResponse parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.ListTasksResponse parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.ListTasksResponse prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:ListTasksResponse]
-   * Result object for tasks/list method containing an array of tasks and pagination information.
-   * 
- * - * Protobuf type {@code a2a.v1.ListTasksResponse} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.ListTasksResponse) - io.a2a.grpc.ListTasksResponseOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.ListTasksResponse.class, io.a2a.grpc.ListTasksResponse.Builder.class); - } - - // Construct using io.a2a.grpc.ListTasksResponse.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - if (tasksBuilder_ == null) { - tasks_ = java.util.Collections.emptyList(); - } else { - tasks_ = null; - tasksBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000001); - nextPageToken_ = ""; - pageSize_ = 0; - totalSize_ = 0; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_ListTasksResponse_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.ListTasksResponse getDefaultInstanceForType() { - return io.a2a.grpc.ListTasksResponse.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.ListTasksResponse build() { - io.a2a.grpc.ListTasksResponse result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.ListTasksResponse buildPartial() { - io.a2a.grpc.ListTasksResponse result = new io.a2a.grpc.ListTasksResponse(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.ListTasksResponse result) { - if (tasksBuilder_ == null) { - if (((bitField0_ & 0x00000001) != 0)) { - tasks_ = java.util.Collections.unmodifiableList(tasks_); - bitField0_ = (bitField0_ & ~0x00000001); - } - result.tasks_ = tasks_; - } else { - result.tasks_ = tasksBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.ListTasksResponse result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000002) != 0)) { - result.nextPageToken_ = nextPageToken_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.pageSize_ = pageSize_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.totalSize_ = totalSize_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.ListTasksResponse) { - return mergeFrom((io.a2a.grpc.ListTasksResponse)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.ListTasksResponse other) { - if (other == io.a2a.grpc.ListTasksResponse.getDefaultInstance()) return this; - if (tasksBuilder_ == null) { - if (!other.tasks_.isEmpty()) { - if (tasks_.isEmpty()) { - tasks_ = other.tasks_; - bitField0_ = (bitField0_ & ~0x00000001); - } else { - ensureTasksIsMutable(); - tasks_.addAll(other.tasks_); - } - onChanged(); - } - } else { - if (!other.tasks_.isEmpty()) { - if (tasksBuilder_.isEmpty()) { - tasksBuilder_.dispose(); - tasksBuilder_ = null; - tasks_ = other.tasks_; - bitField0_ = (bitField0_ & ~0x00000001); - tasksBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetTasksFieldBuilder() : null; - } else { - tasksBuilder_.addAllMessages(other.tasks_); - } - } - } - if (!other.getNextPageToken().isEmpty()) { - nextPageToken_ = other.nextPageToken_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.getPageSize() != 0) { - setPageSize(other.getPageSize()); - } - if (other.getTotalSize() != 0) { - setTotalSize(other.getTotalSize()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - io.a2a.grpc.Task m = - input.readMessage( - io.a2a.grpc.Task.parser(), - extensionRegistry); - if (tasksBuilder_ == null) { - ensureTasksIsMutable(); - tasks_.add(m); - } else { - tasksBuilder_.addMessage(m); - } - break; - } // case 10 - case 18: { - nextPageToken_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 24: { - pageSize_ = input.readInt32(); - bitField0_ |= 0x00000004; - break; - } // case 24 - case 32: { - totalSize_ = input.readInt32(); - bitField0_ |= 0x00000008; - break; - } // case 32 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.util.List tasks_ = - java.util.Collections.emptyList(); - private void ensureTasksIsMutable() { - if (!((bitField0_ & 0x00000001) != 0)) { - tasks_ = new java.util.ArrayList(tasks_); - bitField0_ |= 0x00000001; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> tasksBuilder_; - - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List getTasksList() { - if (tasksBuilder_ == null) { - return java.util.Collections.unmodifiableList(tasks_); - } else { - return tasksBuilder_.getMessageList(); - } - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public int getTasksCount() { - if (tasksBuilder_ == null) { - return tasks_.size(); - } else { - return tasksBuilder_.getCount(); - } - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Task getTasks(int index) { - if (tasksBuilder_ == null) { - return tasks_.get(index); - } else { - return tasksBuilder_.getMessage(index); - } - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setTasks( - int index, io.a2a.grpc.Task value) { - if (tasksBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureTasksIsMutable(); - tasks_.set(index, value); - onChanged(); - } else { - tasksBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setTasks( - int index, io.a2a.grpc.Task.Builder builderForValue) { - if (tasksBuilder_ == null) { - ensureTasksIsMutable(); - tasks_.set(index, builderForValue.build()); - onChanged(); - } else { - tasksBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addTasks(io.a2a.grpc.Task value) { - if (tasksBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureTasksIsMutable(); - tasks_.add(value); - onChanged(); - } else { - tasksBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addTasks( - int index, io.a2a.grpc.Task value) { - if (tasksBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureTasksIsMutable(); - tasks_.add(index, value); - onChanged(); - } else { - tasksBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addTasks( - io.a2a.grpc.Task.Builder builderForValue) { - if (tasksBuilder_ == null) { - ensureTasksIsMutable(); - tasks_.add(builderForValue.build()); - onChanged(); - } else { - tasksBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addTasks( - int index, io.a2a.grpc.Task.Builder builderForValue) { - if (tasksBuilder_ == null) { - ensureTasksIsMutable(); - tasks_.add(index, builderForValue.build()); - onChanged(); - } else { - tasksBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addAllTasks( - java.lang.Iterable values) { - if (tasksBuilder_ == null) { - ensureTasksIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, tasks_); - onChanged(); - } else { - tasksBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearTasks() { - if (tasksBuilder_ == null) { - tasks_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - } else { - tasksBuilder_.clear(); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeTasks(int index) { - if (tasksBuilder_ == null) { - ensureTasksIsMutable(); - tasks_.remove(index); - onChanged(); - } else { - tasksBuilder_.remove(index); - } - return this; - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Task.Builder getTasksBuilder( - int index) { - return internalGetTasksFieldBuilder().getBuilder(index); - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( - int index) { - if (tasksBuilder_ == null) { - return tasks_.get(index); } else { - return tasksBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getTasksOrBuilderList() { - if (tasksBuilder_ != null) { - return tasksBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(tasks_); - } - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Task.Builder addTasksBuilder() { - return internalGetTasksFieldBuilder().addBuilder( - io.a2a.grpc.Task.getDefaultInstance()); - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Task.Builder addTasksBuilder( - int index) { - return internalGetTasksFieldBuilder().addBuilder( - index, io.a2a.grpc.Task.getDefaultInstance()); - } - /** - *
-     * Array of tasks matching the specified criteria.
-     * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getTasksBuilderList() { - return internalGetTasksFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> - internalGetTasksFieldBuilder() { - if (tasksBuilder_ == null) { - tasksBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder>( - tasks_, - ((bitField0_ & 0x00000001) != 0), - getParentForChildren(), - isClean()); - tasks_ = null; - } - return tasksBuilder_; - } - - private java.lang.Object nextPageToken_ = ""; - /** - *
-     * Token for retrieving the next page. Empty string if no more results.
-     * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The nextPageToken. - */ - public java.lang.String getNextPageToken() { - java.lang.Object ref = nextPageToken_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - nextPageToken_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Token for retrieving the next page. Empty string if no more results.
-     * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for nextPageToken. - */ - public com.google.protobuf.ByteString - getNextPageTokenBytes() { - java.lang.Object ref = nextPageToken_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - nextPageToken_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Token for retrieving the next page. Empty string if no more results.
-     * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The nextPageToken to set. - * @return This builder for chaining. - */ - public Builder setNextPageToken( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - nextPageToken_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Token for retrieving the next page. Empty string if no more results.
-     * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearNextPageToken() { - nextPageToken_ = getDefaultInstance().getNextPageToken(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * Token for retrieving the next page. Empty string if no more results.
-     * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for nextPageToken to set. - * @return This builder for chaining. - */ - public Builder setNextPageTokenBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - nextPageToken_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private int pageSize_ ; - /** - *
-     * The size of page requested.
-     * 
- * - * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The pageSize. - */ - @java.lang.Override - public int getPageSize() { - return pageSize_; - } - /** - *
-     * The size of page requested.
-     * 
- * - * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The pageSize to set. - * @return This builder for chaining. - */ - public Builder setPageSize(int value) { - - pageSize_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The size of page requested.
-     * 
- * - * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearPageSize() { - bitField0_ = (bitField0_ & ~0x00000004); - pageSize_ = 0; - onChanged(); - return this; - } - - private int totalSize_ ; - /** - *
-     * Total number of tasks available (before pagination).
-     * 
- * - * int32 total_size = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The totalSize. - */ - @java.lang.Override - public int getTotalSize() { - return totalSize_; - } - /** - *
-     * Total number of tasks available (before pagination).
-     * 
- * - * int32 total_size = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The totalSize to set. - * @return This builder for chaining. - */ - public Builder setTotalSize(int value) { - - totalSize_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Total number of tasks available (before pagination).
-     * 
- * - * int32 total_size = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTotalSize() { - bitField0_ = (bitField0_ & ~0x00000008); - totalSize_ = 0; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.ListTasksResponse) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.ListTasksResponse) - private static final io.a2a.grpc.ListTasksResponse DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.ListTasksResponse(); - } - - public static io.a2a.grpc.ListTasksResponse getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public ListTasksResponse parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.ListTasksResponse getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java deleted file mode 100644 index 430700f61..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/ListTasksResponseOrBuilder.java +++ /dev/null @@ -1,96 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface ListTasksResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.ListTasksResponse) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getTasksList(); - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.Task getTasks(int index); - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - int getTasksCount(); - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getTasksOrBuilderList(); - /** - *
-   * Array of tasks matching the specified criteria.
-   * 
- * - * repeated .a2a.v1.Task tasks = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.TaskOrBuilder getTasksOrBuilder( - int index); - - /** - *
-   * Token for retrieving the next page. Empty string if no more results.
-   * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The nextPageToken. - */ - java.lang.String getNextPageToken(); - /** - *
-   * Token for retrieving the next page. Empty string if no more results.
-   * 
- * - * string next_page_token = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for nextPageToken. - */ - com.google.protobuf.ByteString - getNextPageTokenBytes(); - - /** - *
-   * The size of page requested.
-   * 
- * - * int32 page_size = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The pageSize. - */ - int getPageSize(); - - /** - *
-   * Total number of tasks available (before pagination).
-   * 
- * - * int32 total_size = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The totalSize. - */ - int getTotalSize(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Message.java b/spec-grpc/src/main/java/io/a2a/grpc/Message.java deleted file mode 100644 index e8f296411..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/Message.java +++ /dev/null @@ -1,2224 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:Message]
- * Message is one unit of communication between client and server. It can be
- * associated with a context and/or a task. For server messages, context_id must
- * be provided, and task_id only if a task was created. For client messages, both
- * fields are optional, with the caveat that if both are provided, they have to
- * match (the context_id has to be the one that is set on the task). If only
- * task_id is provided, the server will infer context_id from it.
- * 
- * - * Protobuf type {@code a2a.v1.Message} - */ -@com.google.protobuf.Generated -public final class Message extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Message) - MessageOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "Message"); - } - // Use Message.newBuilder() to construct. - private Message(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private Message() { - messageId_ = ""; - contextId_ = ""; - taskId_ = ""; - role_ = 0; - parts_ = java.util.Collections.emptyList(); - extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - referenceTaskIds_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Message.class, io.a2a.grpc.Message.Builder.class); - } - - private int bitField0_; - public static final int MESSAGE_ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object messageId_ = ""; - /** - *
-   * The unique identifier (e.g. UUID) of the message. This is required and
-   * created by the message creator.
-   * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The messageId. - */ - @java.lang.Override - public java.lang.String getMessageId() { - java.lang.Object ref = messageId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - messageId_ = s; - return s; - } - } - /** - *
-   * The unique identifier (e.g. UUID) of the message. This is required and
-   * created by the message creator.
-   * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for messageId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getMessageIdBytes() { - java.lang.Object ref = messageId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - messageId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONTEXT_ID_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object contextId_ = ""; - /** - *
-   * The context id of the message. This is optional and if set, the message
-   * will be associated with the given context.
-   * 
- * - * string context_id = 2; - * @return The contextId. - */ - @java.lang.Override - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } - } - /** - *
-   * The context id of the message. This is optional and if set, the message
-   * will be associated with the given context.
-   * 
- * - * string context_id = 2; - * @return The bytes for contextId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The task id of the message. This is optional and if set, the message
-   * will be associated with the given task.
-   * 
- * - * string task_id = 3; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The task id of the message. This is optional and if set, the message
-   * will be associated with the given task.
-   * 
- * - * string task_id = 3; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ROLE_FIELD_NUMBER = 4; - private int role_ = 0; - /** - *
-   * Identifies the sender of the message.
-   * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The enum numeric value on the wire for role. - */ - @java.lang.Override public int getRoleValue() { - return role_; - } - /** - *
-   * Identifies the sender of the message.
-   * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The role. - */ - @java.lang.Override public io.a2a.grpc.Role getRole() { - io.a2a.grpc.Role result = io.a2a.grpc.Role.forNumber(role_); - return result == null ? io.a2a.grpc.Role.UNRECOGNIZED : result; - } - - public static final int PARTS_FIELD_NUMBER = 5; - @SuppressWarnings("serial") - private java.util.List parts_; - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List getPartsList() { - return parts_; - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public java.util.List - getPartsOrBuilderList() { - return parts_; - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public int getPartsCount() { - return parts_.size(); - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.Part getParts(int index) { - return parts_.get(index); - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( - int index) { - return parts_.get(index); - } - - public static final int METADATA_FIELD_NUMBER = 6; - private com.google.protobuf.Struct metadata_; - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * Any optional metadata to provide along with the message.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - @java.lang.Override - public boolean hasMetadata() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * Any optional metadata to provide along with the message.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - @java.lang.Override - public com.google.protobuf.Struct getMetadata() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * Any optional metadata to provide along with the message.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - - public static final int EXTENSIONS_FIELD_NUMBER = 7; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @return A list containing the extensions. - */ - public com.google.protobuf.ProtocolStringList - getExtensionsList() { - return extensions_; - } - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @return The count of extensions. - */ - public int getExtensionsCount() { - return extensions_.size(); - } - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the element to return. - * @return The extensions at the given index. - */ - public java.lang.String getExtensions(int index) { - return extensions_.get(index); - } - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the value to return. - * @return The bytes of the extensions at the given index. - */ - public com.google.protobuf.ByteString - getExtensionsBytes(int index) { - return extensions_.getByteString(index); - } - - public static final int REFERENCE_TASK_IDS_FIELD_NUMBER = 8; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList referenceTaskIds_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @return A list containing the referenceTaskIds. - */ - public com.google.protobuf.ProtocolStringList - getReferenceTaskIdsList() { - return referenceTaskIds_; - } - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @return The count of referenceTaskIds. - */ - public int getReferenceTaskIdsCount() { - return referenceTaskIds_.size(); - } - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @param index The index of the element to return. - * @return The referenceTaskIds at the given index. - */ - public java.lang.String getReferenceTaskIds(int index) { - return referenceTaskIds_.get(index); - } - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @param index The index of the value to return. - * @return The bytes of the referenceTaskIds at the given index. - */ - public com.google.protobuf.ByteString - getReferenceTaskIdsBytes(int index) { - return referenceTaskIds_.getByteString(index); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(messageId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, messageId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); - } - if (role_ != io.a2a.grpc.Role.ROLE_UNSPECIFIED.getNumber()) { - output.writeEnum(4, role_); - } - for (int i = 0; i < parts_.size(); i++) { - output.writeMessage(5, parts_.get(i)); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(6, getMetadata()); - } - for (int i = 0; i < extensions_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 7, extensions_.getRaw(i)); - } - for (int i = 0; i < referenceTaskIds_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 8, referenceTaskIds_.getRaw(i)); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(messageId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, messageId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); - } - if (role_ != io.a2a.grpc.Role.ROLE_UNSPECIFIED.getNumber()) { - size += com.google.protobuf.CodedOutputStream - .computeEnumSize(4, role_); - } - for (int i = 0; i < parts_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, parts_.get(i)); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getMetadata()); - } - { - int dataSize = 0; - for (int i = 0; i < extensions_.size(); i++) { - dataSize += computeStringSizeNoTag(extensions_.getRaw(i)); - } - size += dataSize; - size += 1 * getExtensionsList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < referenceTaskIds_.size(); i++) { - dataSize += computeStringSizeNoTag(referenceTaskIds_.getRaw(i)); - } - size += dataSize; - size += 1 * getReferenceTaskIdsList().size(); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.Message)) { - return super.equals(obj); - } - io.a2a.grpc.Message other = (io.a2a.grpc.Message) obj; - - if (!getMessageId() - .equals(other.getMessageId())) return false; - if (!getContextId() - .equals(other.getContextId())) return false; - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (role_ != other.role_) return false; - if (!getPartsList() - .equals(other.getPartsList())) return false; - if (hasMetadata() != other.hasMetadata()) return false; - if (hasMetadata()) { - if (!getMetadata() - .equals(other.getMetadata())) return false; - } - if (!getExtensionsList() - .equals(other.getExtensionsList())) return false; - if (!getReferenceTaskIdsList() - .equals(other.getReferenceTaskIdsList())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + MESSAGE_ID_FIELD_NUMBER; - hash = (53 * hash) + getMessageId().hashCode(); - hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; - hash = (53 * hash) + getContextId().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + ROLE_FIELD_NUMBER; - hash = (53 * hash) + role_; - if (getPartsCount() > 0) { - hash = (37 * hash) + PARTS_FIELD_NUMBER; - hash = (53 * hash) + getPartsList().hashCode(); - } - if (hasMetadata()) { - hash = (37 * hash) + METADATA_FIELD_NUMBER; - hash = (53 * hash) + getMetadata().hashCode(); - } - if (getExtensionsCount() > 0) { - hash = (37 * hash) + EXTENSIONS_FIELD_NUMBER; - hash = (53 * hash) + getExtensionsList().hashCode(); - } - if (getReferenceTaskIdsCount() > 0) { - hash = (37 * hash) + REFERENCE_TASK_IDS_FIELD_NUMBER; - hash = (53 * hash) + getReferenceTaskIdsList().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.Message parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Message parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Message parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Message parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Message parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Message parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Message parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Message parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.Message parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.Message parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.Message parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Message parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.Message prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:Message]
-   * Message is one unit of communication between client and server. It can be
-   * associated with a context and/or a task. For server messages, context_id must
-   * be provided, and task_id only if a task was created. For client messages, both
-   * fields are optional, with the caveat that if both are provided, they have to
-   * match (the context_id has to be the one that is set on the task). If only
-   * task_id is provided, the server will infer context_id from it.
-   * 
- * - * Protobuf type {@code a2a.v1.Message} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Message) - io.a2a.grpc.MessageOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Message.class, io.a2a.grpc.Message.Builder.class); - } - - // Construct using io.a2a.grpc.Message.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetPartsFieldBuilder(); - internalGetMetadataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - messageId_ = ""; - contextId_ = ""; - taskId_ = ""; - role_ = 0; - if (partsBuilder_ == null) { - parts_ = java.util.Collections.emptyList(); - } else { - parts_ = null; - partsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000010); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - referenceTaskIds_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Message_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.Message getDefaultInstanceForType() { - return io.a2a.grpc.Message.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.Message build() { - io.a2a.grpc.Message result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.Message buildPartial() { - io.a2a.grpc.Message result = new io.a2a.grpc.Message(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.Message result) { - if (partsBuilder_ == null) { - if (((bitField0_ & 0x00000010) != 0)) { - parts_ = java.util.Collections.unmodifiableList(parts_); - bitField0_ = (bitField0_ & ~0x00000010); - } - result.parts_ = parts_; - } else { - result.parts_ = partsBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.Message result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.messageId_ = messageId_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.contextId_ = contextId_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.taskId_ = taskId_; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.role_ = role_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000020) != 0)) { - result.metadata_ = metadataBuilder_ == null - ? metadata_ - : metadataBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000040) != 0)) { - extensions_.makeImmutable(); - result.extensions_ = extensions_; - } - if (((from_bitField0_ & 0x00000080) != 0)) { - referenceTaskIds_.makeImmutable(); - result.referenceTaskIds_ = referenceTaskIds_; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.Message) { - return mergeFrom((io.a2a.grpc.Message)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.Message other) { - if (other == io.a2a.grpc.Message.getDefaultInstance()) return this; - if (!other.getMessageId().isEmpty()) { - messageId_ = other.messageId_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getContextId().isEmpty()) { - contextId_ = other.contextId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (other.role_ != 0) { - setRoleValue(other.getRoleValue()); - } - if (partsBuilder_ == null) { - if (!other.parts_.isEmpty()) { - if (parts_.isEmpty()) { - parts_ = other.parts_; - bitField0_ = (bitField0_ & ~0x00000010); - } else { - ensurePartsIsMutable(); - parts_.addAll(other.parts_); - } - onChanged(); - } - } else { - if (!other.parts_.isEmpty()) { - if (partsBuilder_.isEmpty()) { - partsBuilder_.dispose(); - partsBuilder_ = null; - parts_ = other.parts_; - bitField0_ = (bitField0_ & ~0x00000010); - partsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetPartsFieldBuilder() : null; - } else { - partsBuilder_.addAllMessages(other.parts_); - } - } - } - if (other.hasMetadata()) { - mergeMetadata(other.getMetadata()); - } - if (!other.extensions_.isEmpty()) { - if (extensions_.isEmpty()) { - extensions_ = other.extensions_; - bitField0_ |= 0x00000040; - } else { - ensureExtensionsIsMutable(); - extensions_.addAll(other.extensions_); - } - onChanged(); - } - if (!other.referenceTaskIds_.isEmpty()) { - if (referenceTaskIds_.isEmpty()) { - referenceTaskIds_ = other.referenceTaskIds_; - bitField0_ |= 0x00000080; - } else { - ensureReferenceTaskIdsIsMutable(); - referenceTaskIds_.addAll(other.referenceTaskIds_); - } - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - messageId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - contextId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 32: { - role_ = input.readEnum(); - bitField0_ |= 0x00000008; - break; - } // case 32 - case 42: { - io.a2a.grpc.Part m = - input.readMessage( - io.a2a.grpc.Part.parser(), - extensionRegistry); - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.add(m); - } else { - partsBuilder_.addMessage(m); - } - break; - } // case 42 - case 50: { - input.readMessage( - internalGetMetadataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000020; - break; - } // case 50 - case 58: { - java.lang.String s = input.readStringRequireUtf8(); - ensureExtensionsIsMutable(); - extensions_.add(s); - break; - } // case 58 - case 66: { - java.lang.String s = input.readStringRequireUtf8(); - ensureReferenceTaskIdsIsMutable(); - referenceTaskIds_.add(s); - break; - } // case 66 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object messageId_ = ""; - /** - *
-     * The unique identifier (e.g. UUID) of the message. This is required and
-     * created by the message creator.
-     * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The messageId. - */ - public java.lang.String getMessageId() { - java.lang.Object ref = messageId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - messageId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The unique identifier (e.g. UUID) of the message. This is required and
-     * created by the message creator.
-     * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for messageId. - */ - public com.google.protobuf.ByteString - getMessageIdBytes() { - java.lang.Object ref = messageId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - messageId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The unique identifier (e.g. UUID) of the message. This is required and
-     * created by the message creator.
-     * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The messageId to set. - * @return This builder for chaining. - */ - public Builder setMessageId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - messageId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The unique identifier (e.g. UUID) of the message. This is required and
-     * created by the message creator.
-     * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearMessageId() { - messageId_ = getDefaultInstance().getMessageId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The unique identifier (e.g. UUID) of the message. This is required and
-     * created by the message creator.
-     * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for messageId to set. - * @return This builder for chaining. - */ - public Builder setMessageIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - messageId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object contextId_ = ""; - /** - *
-     * The context id of the message. This is optional and if set, the message
-     * will be associated with the given context.
-     * 
- * - * string context_id = 2; - * @return The contextId. - */ - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The context id of the message. This is optional and if set, the message
-     * will be associated with the given context.
-     * 
- * - * string context_id = 2; - * @return The bytes for contextId. - */ - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The context id of the message. This is optional and if set, the message
-     * will be associated with the given context.
-     * 
- * - * string context_id = 2; - * @param value The contextId to set. - * @return This builder for chaining. - */ - public Builder setContextId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The context id of the message. This is optional and if set, the message
-     * will be associated with the given context.
-     * 
- * - * string context_id = 2; - * @return This builder for chaining. - */ - public Builder clearContextId() { - contextId_ = getDefaultInstance().getContextId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The context id of the message. This is optional and if set, the message
-     * will be associated with the given context.
-     * 
- * - * string context_id = 2; - * @param value The bytes for contextId to set. - * @return This builder for chaining. - */ - public Builder setContextIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object taskId_ = ""; - /** - *
-     * The task id of the message. This is optional and if set, the message
-     * will be associated with the given task.
-     * 
- * - * string task_id = 3; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The task id of the message. This is optional and if set, the message
-     * will be associated with the given task.
-     * 
- * - * string task_id = 3; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The task id of the message. This is optional and if set, the message
-     * will be associated with the given task.
-     * 
- * - * string task_id = 3; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The task id of the message. This is optional and if set, the message
-     * will be associated with the given task.
-     * 
- * - * string task_id = 3; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The task id of the message. This is optional and if set, the message
-     * will be associated with the given task.
-     * 
- * - * string task_id = 3; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private int role_ = 0; - /** - *
-     * Identifies the sender of the message.
-     * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The enum numeric value on the wire for role. - */ - @java.lang.Override public int getRoleValue() { - return role_; - } - /** - *
-     * Identifies the sender of the message.
-     * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The enum numeric value on the wire for role to set. - * @return This builder for chaining. - */ - public Builder setRoleValue(int value) { - role_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Identifies the sender of the message.
-     * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The role. - */ - @java.lang.Override - public io.a2a.grpc.Role getRole() { - io.a2a.grpc.Role result = io.a2a.grpc.Role.forNumber(role_); - return result == null ? io.a2a.grpc.Role.UNRECOGNIZED : result; - } - /** - *
-     * Identifies the sender of the message.
-     * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @param value The role to set. - * @return This builder for chaining. - */ - public Builder setRole(io.a2a.grpc.Role value) { - if (value == null) { throw new NullPointerException(); } - bitField0_ |= 0x00000008; - role_ = value.getNumber(); - onChanged(); - return this; - } - /** - *
-     * Identifies the sender of the message.
-     * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearRole() { - bitField0_ = (bitField0_ & ~0x00000008); - role_ = 0; - onChanged(); - return this; - } - - private java.util.List parts_ = - java.util.Collections.emptyList(); - private void ensurePartsIsMutable() { - if (!((bitField0_ & 0x00000010) != 0)) { - parts_ = new java.util.ArrayList(parts_); - bitField0_ |= 0x00000010; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> partsBuilder_; - - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List getPartsList() { - if (partsBuilder_ == null) { - return java.util.Collections.unmodifiableList(parts_); - } else { - return partsBuilder_.getMessageList(); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public int getPartsCount() { - if (partsBuilder_ == null) { - return parts_.size(); - } else { - return partsBuilder_.getCount(); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part getParts(int index) { - if (partsBuilder_ == null) { - return parts_.get(index); - } else { - return partsBuilder_.getMessage(index); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setParts( - int index, io.a2a.grpc.Part value) { - if (partsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensurePartsIsMutable(); - parts_.set(index, value); - onChanged(); - } else { - partsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setParts( - int index, io.a2a.grpc.Part.Builder builderForValue) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.set(index, builderForValue.build()); - onChanged(); - } else { - partsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts(io.a2a.grpc.Part value) { - if (partsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensurePartsIsMutable(); - parts_.add(value); - onChanged(); - } else { - partsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts( - int index, io.a2a.grpc.Part value) { - if (partsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensurePartsIsMutable(); - parts_.add(index, value); - onChanged(); - } else { - partsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts( - io.a2a.grpc.Part.Builder builderForValue) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.add(builderForValue.build()); - onChanged(); - } else { - partsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addParts( - int index, io.a2a.grpc.Part.Builder builderForValue) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.add(index, builderForValue.build()); - onChanged(); - } else { - partsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder addAllParts( - java.lang.Iterable values) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, parts_); - onChanged(); - } else { - partsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearParts() { - if (partsBuilder_ == null) { - parts_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000010); - onChanged(); - } else { - partsBuilder_.clear(); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder removeParts(int index) { - if (partsBuilder_ == null) { - ensurePartsIsMutable(); - parts_.remove(index); - onChanged(); - } else { - partsBuilder_.remove(index); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part.Builder getPartsBuilder( - int index) { - return internalGetPartsFieldBuilder().getBuilder(index); - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PartOrBuilder getPartsOrBuilder( - int index) { - if (partsBuilder_ == null) { - return parts_.get(index); } else { - return partsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getPartsOrBuilderList() { - if (partsBuilder_ != null) { - return partsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(parts_); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part.Builder addPartsBuilder() { - return internalGetPartsFieldBuilder().addBuilder( - io.a2a.grpc.Part.getDefaultInstance()); - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Part.Builder addPartsBuilder( - int index) { - return internalGetPartsFieldBuilder().addBuilder( - index, io.a2a.grpc.Part.getDefaultInstance()); - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * Parts is the container of the message content.
-     * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - public java.util.List - getPartsBuilderList() { - return internalGetPartsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder> - internalGetPartsFieldBuilder() { - if (partsBuilder_ == null) { - partsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Part, io.a2a.grpc.Part.Builder, io.a2a.grpc.PartOrBuilder>( - parts_, - ((bitField0_ & 0x00000010) != 0), - getParentForChildren(), - isClean()); - parts_ = null; - } - return partsBuilder_; - } - - private com.google.protobuf.Struct metadata_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - public boolean hasMetadata() { - return ((bitField0_ & 0x00000020) != 0); - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - public com.google.protobuf.Struct getMetadata() { - if (metadataBuilder_ == null) { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } else { - return metadataBuilder_.getMessage(); - } - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - metadata_ = value; - } else { - metadataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata( - com.google.protobuf.Struct.Builder builderForValue) { - if (metadataBuilder_ == null) { - metadata_ = builderForValue.build(); - } else { - metadataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder mergeMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000020) != 0) && - metadata_ != null && - metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { - getMetadataBuilder().mergeFrom(value); - } else { - metadata_ = value; - } - } else { - metadataBuilder_.mergeFrom(value); - } - if (metadata_ != null) { - bitField0_ |= 0x00000020; - onChanged(); - } - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000020); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000020; - onChanged(); - return internalGetMetadataFieldBuilder().getBuilder(); - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - if (metadataBuilder_ != null) { - return metadataBuilder_.getMessageOrBuilder(); - } else { - return metadata_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * Any optional metadata to provide along with the message.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetMetadataFieldBuilder() { - if (metadataBuilder_ == null) { - metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getMetadata(), - getParentForChildren(), - isClean()); - metadata_ = null; - } - return metadataBuilder_; - } - - private com.google.protobuf.LazyStringArrayList extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureExtensionsIsMutable() { - if (!extensions_.isModifiable()) { - extensions_ = new com.google.protobuf.LazyStringArrayList(extensions_); - } - bitField0_ |= 0x00000040; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @return A list containing the extensions. - */ - public com.google.protobuf.ProtocolStringList - getExtensionsList() { - extensions_.makeImmutable(); - return extensions_; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @return The count of extensions. - */ - public int getExtensionsCount() { - return extensions_.size(); - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @param index The index of the element to return. - * @return The extensions at the given index. - */ - public java.lang.String getExtensions(int index) { - return extensions_.get(index); - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @param index The index of the value to return. - * @return The bytes of the extensions at the given index. - */ - public com.google.protobuf.ByteString - getExtensionsBytes(int index) { - return extensions_.getByteString(index); - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @param index The index to set the value at. - * @param value The extensions to set. - * @return This builder for chaining. - */ - public Builder setExtensions( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureExtensionsIsMutable(); - extensions_.set(index, value); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @param value The extensions to add. - * @return This builder for chaining. - */ - public Builder addExtensions( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureExtensionsIsMutable(); - extensions_.add(value); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @param values The extensions to add. - * @return This builder for chaining. - */ - public Builder addAllExtensions( - java.lang.Iterable values) { - ensureExtensionsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, extensions_); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @return This builder for chaining. - */ - public Builder clearExtensions() { - extensions_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000040);; - onChanged(); - return this; - } - /** - *
-     * The URIs of extensions that are present or contributed to this Message.
-     * 
- * - * repeated string extensions = 7; - * @param value The bytes of the extensions to add. - * @return This builder for chaining. - */ - public Builder addExtensionsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureExtensionsIsMutable(); - extensions_.add(value); - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - - private com.google.protobuf.LazyStringArrayList referenceTaskIds_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureReferenceTaskIdsIsMutable() { - if (!referenceTaskIds_.isModifiable()) { - referenceTaskIds_ = new com.google.protobuf.LazyStringArrayList(referenceTaskIds_); - } - bitField0_ |= 0x00000080; - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @return A list containing the referenceTaskIds. - */ - public com.google.protobuf.ProtocolStringList - getReferenceTaskIdsList() { - referenceTaskIds_.makeImmutable(); - return referenceTaskIds_; - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @return The count of referenceTaskIds. - */ - public int getReferenceTaskIdsCount() { - return referenceTaskIds_.size(); - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @param index The index of the element to return. - * @return The referenceTaskIds at the given index. - */ - public java.lang.String getReferenceTaskIds(int index) { - return referenceTaskIds_.get(index); - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @param index The index of the value to return. - * @return The bytes of the referenceTaskIds at the given index. - */ - public com.google.protobuf.ByteString - getReferenceTaskIdsBytes(int index) { - return referenceTaskIds_.getByteString(index); - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @param index The index to set the value at. - * @param value The referenceTaskIds to set. - * @return This builder for chaining. - */ - public Builder setReferenceTaskIds( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureReferenceTaskIdsIsMutable(); - referenceTaskIds_.set(index, value); - bitField0_ |= 0x00000080; - onChanged(); - return this; - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @param value The referenceTaskIds to add. - * @return This builder for chaining. - */ - public Builder addReferenceTaskIds( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureReferenceTaskIdsIsMutable(); - referenceTaskIds_.add(value); - bitField0_ |= 0x00000080; - onChanged(); - return this; - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @param values The referenceTaskIds to add. - * @return This builder for chaining. - */ - public Builder addAllReferenceTaskIds( - java.lang.Iterable values) { - ensureReferenceTaskIdsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, referenceTaskIds_); - bitField0_ |= 0x00000080; - onChanged(); - return this; - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @return This builder for chaining. - */ - public Builder clearReferenceTaskIds() { - referenceTaskIds_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000080);; - onChanged(); - return this; - } - /** - *
-     * A list of task IDs that this message references for additional context.
-     * 
- * - * repeated string reference_task_ids = 8; - * @param value The bytes of the referenceTaskIds to add. - * @return This builder for chaining. - */ - public Builder addReferenceTaskIdsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureReferenceTaskIdsIsMutable(); - referenceTaskIds_.add(value); - bitField0_ |= 0x00000080; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.Message) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.Message) - private static final io.a2a.grpc.Message DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.Message(); - } - - public static io.a2a.grpc.Message getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public Message parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.Message getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java deleted file mode 100644 index cfd7ea3ef..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/MessageOrBuilder.java +++ /dev/null @@ -1,258 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface MessageOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Message) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The unique identifier (e.g. UUID) of the message. This is required and
-   * created by the message creator.
-   * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The messageId. - */ - java.lang.String getMessageId(); - /** - *
-   * The unique identifier (e.g. UUID) of the message. This is required and
-   * created by the message creator.
-   * 
- * - * string message_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for messageId. - */ - com.google.protobuf.ByteString - getMessageIdBytes(); - - /** - *
-   * The context id of the message. This is optional and if set, the message
-   * will be associated with the given context.
-   * 
- * - * string context_id = 2; - * @return The contextId. - */ - java.lang.String getContextId(); - /** - *
-   * The context id of the message. This is optional and if set, the message
-   * will be associated with the given context.
-   * 
- * - * string context_id = 2; - * @return The bytes for contextId. - */ - com.google.protobuf.ByteString - getContextIdBytes(); - - /** - *
-   * The task id of the message. This is optional and if set, the message
-   * will be associated with the given task.
-   * 
- * - * string task_id = 3; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The task id of the message. This is optional and if set, the message
-   * will be associated with the given task.
-   * 
- * - * string task_id = 3; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * Identifies the sender of the message.
-   * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The enum numeric value on the wire for role. - */ - int getRoleValue(); - /** - *
-   * Identifies the sender of the message.
-   * 
- * - * .a2a.v1.Role role = 4 [(.google.api.field_behavior) = REQUIRED]; - * @return The role. - */ - io.a2a.grpc.Role getRole(); - - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getPartsList(); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.Part getParts(int index); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - int getPartsCount(); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - java.util.List - getPartsOrBuilderList(); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * Parts is the container of the message content.
-   * 
- * - * repeated .a2a.v1.Part parts = 5 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.PartOrBuilder getPartsOrBuilder( - int index); - - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * Any optional metadata to provide along with the message.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - boolean hasMetadata(); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * Any optional metadata to provide along with the message.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - com.google.protobuf.Struct getMetadata(); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * Any optional metadata to provide along with the message.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); - - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @return A list containing the extensions. - */ - java.util.List - getExtensionsList(); - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @return The count of extensions. - */ - int getExtensionsCount(); - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the element to return. - * @return The extensions at the given index. - */ - java.lang.String getExtensions(int index); - /** - *
-   * The URIs of extensions that are present or contributed to this Message.
-   * 
- * - * repeated string extensions = 7; - * @param index The index of the value to return. - * @return The bytes of the extensions at the given index. - */ - com.google.protobuf.ByteString - getExtensionsBytes(int index); - - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @return A list containing the referenceTaskIds. - */ - java.util.List - getReferenceTaskIdsList(); - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @return The count of referenceTaskIds. - */ - int getReferenceTaskIdsCount(); - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @param index The index of the element to return. - * @return The referenceTaskIds at the given index. - */ - java.lang.String getReferenceTaskIds(int index); - /** - *
-   * A list of task IDs that this message references for additional context.
-   * 
- * - * repeated string reference_task_ids = 8; - * @param index The index of the value to return. - * @return The bytes of the referenceTaskIds at the given index. - */ - com.google.protobuf.ByteString - getReferenceTaskIdsBytes(int index); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java deleted file mode 100644 index b85fce3e4..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecurityScheme.java +++ /dev/null @@ -1,540 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:MutualTLSSecurityScheme]
- * Defines a security scheme using mTLS authentication.
- * 
- * - * Protobuf type {@code a2a.v1.MutualTlsSecurityScheme} - */ -@com.google.protobuf.Generated -public final class MutualTlsSecurityScheme extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.MutualTlsSecurityScheme) - MutualTlsSecuritySchemeOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "MutualTlsSecurityScheme"); - } - // Use MutualTlsSecurityScheme.newBuilder() to construct. - private MutualTlsSecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private MutualTlsSecurityScheme() { - description_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.MutualTlsSecurityScheme.class, io.a2a.grpc.MutualTlsSecurityScheme.Builder.class); - } - - public static final int DESCRIPTION_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.MutualTlsSecurityScheme)) { - return super.equals(obj); - } - io.a2a.grpc.MutualTlsSecurityScheme other = (io.a2a.grpc.MutualTlsSecurityScheme) obj; - - if (!getDescription() - .equals(other.getDescription())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.MutualTlsSecurityScheme parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.MutualTlsSecurityScheme parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.MutualTlsSecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.MutualTlsSecurityScheme prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:MutualTLSSecurityScheme]
-   * Defines a security scheme using mTLS authentication.
-   * 
- * - * Protobuf type {@code a2a.v1.MutualTlsSecurityScheme} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.MutualTlsSecurityScheme) - io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.MutualTlsSecurityScheme.class, io.a2a.grpc.MutualTlsSecurityScheme.Builder.class); - } - - // Construct using io.a2a.grpc.MutualTlsSecurityScheme.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - description_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_MutualTlsSecurityScheme_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() { - return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.MutualTlsSecurityScheme build() { - io.a2a.grpc.MutualTlsSecurityScheme result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.MutualTlsSecurityScheme buildPartial() { - io.a2a.grpc.MutualTlsSecurityScheme result = new io.a2a.grpc.MutualTlsSecurityScheme(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.MutualTlsSecurityScheme result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.description_ = description_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.MutualTlsSecurityScheme) { - return mergeFrom((io.a2a.grpc.MutualTlsSecurityScheme)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.MutualTlsSecurityScheme other) { - if (other == io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance()) return this; - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000001; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object description_ = ""; - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.MutualTlsSecurityScheme) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.MutualTlsSecurityScheme) - private static final io.a2a.grpc.MutualTlsSecurityScheme DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.MutualTlsSecurityScheme(); - } - - public static io.a2a.grpc.MutualTlsSecurityScheme getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public MutualTlsSecurityScheme parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.MutualTlsSecurityScheme getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java deleted file mode 100644 index c5c606198..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/MutualTlsSecuritySchemeOrBuilder.java +++ /dev/null @@ -1,32 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface MutualTlsSecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.MutualTlsSecurityScheme) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java deleted file mode 100644 index 6b3d725e8..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecurityScheme.java +++ /dev/null @@ -1,952 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:OAuth2SecurityScheme]
- * Defines a security scheme using OAuth 2.0.
- * 
- * - * Protobuf type {@code a2a.v1.OAuth2SecurityScheme} - */ -@com.google.protobuf.Generated -public final class OAuth2SecurityScheme extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.OAuth2SecurityScheme) - OAuth2SecuritySchemeOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "OAuth2SecurityScheme"); - } - // Use OAuth2SecurityScheme.newBuilder() to construct. - private OAuth2SecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private OAuth2SecurityScheme() { - description_ = ""; - oauth2MetadataUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.OAuth2SecurityScheme.class, io.a2a.grpc.OAuth2SecurityScheme.Builder.class); - } - - private int bitField0_; - public static final int DESCRIPTION_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int FLOWS_FIELD_NUMBER = 2; - private io.a2a.grpc.OAuthFlows flows_; - /** - *
-   * An object containing configuration information for the supported OAuth 2.0 flows.
-   * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the flows field is set. - */ - @java.lang.Override - public boolean hasFlows() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * An object containing configuration information for the supported OAuth 2.0 flows.
-   * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The flows. - */ - @java.lang.Override - public io.a2a.grpc.OAuthFlows getFlows() { - return flows_ == null ? io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_; - } - /** - *
-   * An object containing configuration information for the supported OAuth 2.0 flows.
-   * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { - return flows_ == null ? io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_; - } - - public static final int OAUTH2_METADATA_URL_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object oauth2MetadataUrl_ = ""; - /** - *
-   * URL to the oauth2 authorization server metadata
-   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-   * 
- * - * string oauth2_metadata_url = 3; - * @return The oauth2MetadataUrl. - */ - @java.lang.Override - public java.lang.String getOauth2MetadataUrl() { - java.lang.Object ref = oauth2MetadataUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - oauth2MetadataUrl_ = s; - return s; - } - } - /** - *
-   * URL to the oauth2 authorization server metadata
-   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-   * 
- * - * string oauth2_metadata_url = 3; - * @return The bytes for oauth2MetadataUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getOauth2MetadataUrlBytes() { - java.lang.Object ref = oauth2MetadataUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - oauth2MetadataUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(2, getFlows()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(oauth2MetadataUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, oauth2MetadataUrl_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getFlows()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(oauth2MetadataUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, oauth2MetadataUrl_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.OAuth2SecurityScheme)) { - return super.equals(obj); - } - io.a2a.grpc.OAuth2SecurityScheme other = (io.a2a.grpc.OAuth2SecurityScheme) obj; - - if (!getDescription() - .equals(other.getDescription())) return false; - if (hasFlows() != other.hasFlows()) return false; - if (hasFlows()) { - if (!getFlows() - .equals(other.getFlows())) return false; - } - if (!getOauth2MetadataUrl() - .equals(other.getOauth2MetadataUrl())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - if (hasFlows()) { - hash = (37 * hash) + FLOWS_FIELD_NUMBER; - hash = (53 * hash) + getFlows().hashCode(); - } - hash = (37 * hash) + OAUTH2_METADATA_URL_FIELD_NUMBER; - hash = (53 * hash) + getOauth2MetadataUrl().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.OAuth2SecurityScheme parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.OAuth2SecurityScheme parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.OAuth2SecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.OAuth2SecurityScheme prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:OAuth2SecurityScheme]
-   * Defines a security scheme using OAuth 2.0.
-   * 
- * - * Protobuf type {@code a2a.v1.OAuth2SecurityScheme} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.OAuth2SecurityScheme) - io.a2a.grpc.OAuth2SecuritySchemeOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.OAuth2SecurityScheme.class, io.a2a.grpc.OAuth2SecurityScheme.Builder.class); - } - - // Construct using io.a2a.grpc.OAuth2SecurityScheme.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetFlowsFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - description_ = ""; - flows_ = null; - if (flowsBuilder_ != null) { - flowsBuilder_.dispose(); - flowsBuilder_ = null; - } - oauth2MetadataUrl_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuth2SecurityScheme_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.OAuth2SecurityScheme getDefaultInstanceForType() { - return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.OAuth2SecurityScheme build() { - io.a2a.grpc.OAuth2SecurityScheme result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.OAuth2SecurityScheme buildPartial() { - io.a2a.grpc.OAuth2SecurityScheme result = new io.a2a.grpc.OAuth2SecurityScheme(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.OAuth2SecurityScheme result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.description_ = description_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000002) != 0)) { - result.flows_ = flowsBuilder_ == null - ? flows_ - : flowsBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.oauth2MetadataUrl_ = oauth2MetadataUrl_; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.OAuth2SecurityScheme) { - return mergeFrom((io.a2a.grpc.OAuth2SecurityScheme)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.OAuth2SecurityScheme other) { - if (other == io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance()) return this; - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (other.hasFlows()) { - mergeFlows(other.getFlows()); - } - if (!other.getOauth2MetadataUrl().isEmpty()) { - oauth2MetadataUrl_ = other.oauth2MetadataUrl_; - bitField0_ |= 0x00000004; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - input.readMessage( - internalGetFlowsFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - oauth2MetadataUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object description_ = ""; - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private io.a2a.grpc.OAuthFlows flows_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OAuthFlows, io.a2a.grpc.OAuthFlows.Builder, io.a2a.grpc.OAuthFlowsOrBuilder> flowsBuilder_; - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the flows field is set. - */ - public boolean hasFlows() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The flows. - */ - public io.a2a.grpc.OAuthFlows getFlows() { - if (flowsBuilder_ == null) { - return flows_ == null ? io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_; - } else { - return flowsBuilder_.getMessage(); - } - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setFlows(io.a2a.grpc.OAuthFlows value) { - if (flowsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - flows_ = value; - } else { - flowsBuilder_.setMessage(value); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setFlows( - io.a2a.grpc.OAuthFlows.Builder builderForValue) { - if (flowsBuilder_ == null) { - flows_ = builderForValue.build(); - } else { - flowsBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeFlows(io.a2a.grpc.OAuthFlows value) { - if (flowsBuilder_ == null) { - if (((bitField0_ & 0x00000002) != 0) && - flows_ != null && - flows_ != io.a2a.grpc.OAuthFlows.getDefaultInstance()) { - getFlowsBuilder().mergeFrom(value); - } else { - flows_ = value; - } - } else { - flowsBuilder_.mergeFrom(value); - } - if (flows_ != null) { - bitField0_ |= 0x00000002; - onChanged(); - } - return this; - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearFlows() { - bitField0_ = (bitField0_ & ~0x00000002); - flows_ = null; - if (flowsBuilder_ != null) { - flowsBuilder_.dispose(); - flowsBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.OAuthFlows.Builder getFlowsBuilder() { - bitField0_ |= 0x00000002; - onChanged(); - return internalGetFlowsFieldBuilder().getBuilder(); - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder() { - if (flowsBuilder_ != null) { - return flowsBuilder_.getMessageOrBuilder(); - } else { - return flows_ == null ? - io.a2a.grpc.OAuthFlows.getDefaultInstance() : flows_; - } - } - /** - *
-     * An object containing configuration information for the supported OAuth 2.0 flows.
-     * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OAuthFlows, io.a2a.grpc.OAuthFlows.Builder, io.a2a.grpc.OAuthFlowsOrBuilder> - internalGetFlowsFieldBuilder() { - if (flowsBuilder_ == null) { - flowsBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OAuthFlows, io.a2a.grpc.OAuthFlows.Builder, io.a2a.grpc.OAuthFlowsOrBuilder>( - getFlows(), - getParentForChildren(), - isClean()); - flows_ = null; - } - return flowsBuilder_; - } - - private java.lang.Object oauth2MetadataUrl_ = ""; - /** - *
-     * URL to the oauth2 authorization server metadata
-     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-     * 
- * - * string oauth2_metadata_url = 3; - * @return The oauth2MetadataUrl. - */ - public java.lang.String getOauth2MetadataUrl() { - java.lang.Object ref = oauth2MetadataUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - oauth2MetadataUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * URL to the oauth2 authorization server metadata
-     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-     * 
- * - * string oauth2_metadata_url = 3; - * @return The bytes for oauth2MetadataUrl. - */ - public com.google.protobuf.ByteString - getOauth2MetadataUrlBytes() { - java.lang.Object ref = oauth2MetadataUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - oauth2MetadataUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * URL to the oauth2 authorization server metadata
-     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-     * 
- * - * string oauth2_metadata_url = 3; - * @param value The oauth2MetadataUrl to set. - * @return This builder for chaining. - */ - public Builder setOauth2MetadataUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - oauth2MetadataUrl_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * URL to the oauth2 authorization server metadata
-     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-     * 
- * - * string oauth2_metadata_url = 3; - * @return This builder for chaining. - */ - public Builder clearOauth2MetadataUrl() { - oauth2MetadataUrl_ = getDefaultInstance().getOauth2MetadataUrl(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * URL to the oauth2 authorization server metadata
-     * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-     * 
- * - * string oauth2_metadata_url = 3; - * @param value The bytes for oauth2MetadataUrl to set. - * @return This builder for chaining. - */ - public Builder setOauth2MetadataUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - oauth2MetadataUrl_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.OAuth2SecurityScheme) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.OAuth2SecurityScheme) - private static final io.a2a.grpc.OAuth2SecurityScheme DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.OAuth2SecurityScheme(); - } - - public static io.a2a.grpc.OAuth2SecurityScheme getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public OAuth2SecurityScheme parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.OAuth2SecurityScheme getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java deleted file mode 100644 index 52b49d1c3..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuth2SecuritySchemeOrBuilder.java +++ /dev/null @@ -1,81 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface OAuth2SecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.OAuth2SecurityScheme) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * An object containing configuration information for the supported OAuth 2.0 flows.
-   * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the flows field is set. - */ - boolean hasFlows(); - /** - *
-   * An object containing configuration information for the supported OAuth 2.0 flows.
-   * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The flows. - */ - io.a2a.grpc.OAuthFlows getFlows(); - /** - *
-   * An object containing configuration information for the supported OAuth 2.0 flows.
-   * 
- * - * .a2a.v1.OAuthFlows flows = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.OAuthFlowsOrBuilder getFlowsOrBuilder(); - - /** - *
-   * URL to the oauth2 authorization server metadata
-   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-   * 
- * - * string oauth2_metadata_url = 3; - * @return The oauth2MetadataUrl. - */ - java.lang.String getOauth2MetadataUrl(); - /** - *
-   * URL to the oauth2 authorization server metadata
-   * RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required.
-   * 
- * - * string oauth2_metadata_url = 3; - * @return The bytes for oauth2MetadataUrl. - */ - com.google.protobuf.ByteString - getOauth2MetadataUrlBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java deleted file mode 100644 index 8b1a661f7..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlows.java +++ /dev/null @@ -1,1651 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:OAuthFlows]
- * Defines the configuration for the supported OAuth 2.0 flows.
- * 
- * - * Protobuf type {@code a2a.v1.OAuthFlows} - */ -@com.google.protobuf.Generated -public final class OAuthFlows extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.OAuthFlows) - OAuthFlowsOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "OAuthFlows"); - } - // Use OAuthFlows.newBuilder() to construct. - private OAuthFlows(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private OAuthFlows() { - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.OAuthFlows.class, io.a2a.grpc.OAuthFlows.Builder.class); - } - - private int flowCase_ = 0; - @SuppressWarnings("serial") - private java.lang.Object flow_; - public enum FlowCase - implements com.google.protobuf.Internal.EnumLite, - com.google.protobuf.AbstractMessage.InternalOneOfEnum { - AUTHORIZATION_CODE(1), - CLIENT_CREDENTIALS(2), - @java.lang.Deprecated IMPLICIT(3), - @java.lang.Deprecated PASSWORD(4), - DEVICE_CODE(5), - FLOW_NOT_SET(0); - private final int value; - private FlowCase(int value) { - this.value = value; - } - /** - * @param value The number of the enum to look for. - * @return The enum associated with the given number. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static FlowCase valueOf(int value) { - return forNumber(value); - } - - public static FlowCase forNumber(int value) { - switch (value) { - case 1: return AUTHORIZATION_CODE; - case 2: return CLIENT_CREDENTIALS; - case 3: return IMPLICIT; - case 4: return PASSWORD; - case 5: return DEVICE_CODE; - case 0: return FLOW_NOT_SET; - default: return null; - } - } - public int getNumber() { - return this.value; - } - }; - - public FlowCase - getFlowCase() { - return FlowCase.forNumber( - flowCase_); - } - - public static final int AUTHORIZATION_CODE_FIELD_NUMBER = 1; - /** - *
-   * Configuration for the OAuth Authorization Code flow.
-   * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - * @return Whether the authorizationCode field is set. - */ - @java.lang.Override - public boolean hasAuthorizationCode() { - return flowCase_ == 1; - } - /** - *
-   * Configuration for the OAuth Authorization Code flow.
-   * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - * @return The authorizationCode. - */ - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() { - if (flowCase_ == 1) { - return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_; - } - return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); - } - /** - *
-   * Configuration for the OAuth Authorization Code flow.
-   * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() { - if (flowCase_ == 1) { - return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_; - } - return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); - } - - public static final int CLIENT_CREDENTIALS_FIELD_NUMBER = 2; - /** - *
-   * Configuration for the OAuth Client Credentials flow.
-   * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - * @return Whether the clientCredentials field is set. - */ - @java.lang.Override - public boolean hasClientCredentials() { - return flowCase_ == 2; - } - /** - *
-   * Configuration for the OAuth Client Credentials flow.
-   * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - * @return The clientCredentials. - */ - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() { - if (flowCase_ == 2) { - return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_; - } - return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); - } - /** - *
-   * Configuration for the OAuth Client Credentials flow.
-   * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() { - if (flowCase_ == 2) { - return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_; - } - return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); - } - - public static final int IMPLICIT_FIELD_NUMBER = 3; - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 - * @return Whether the implicit field is set. - */ - @java.lang.Override - @java.lang.Deprecated public boolean hasImplicit() { - return flowCase_ == 3; - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 - * @return The implicit. - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow getImplicit() { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - - public static final int PASSWORD_FIELD_NUMBER = 4; - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 - * @return Whether the password field is set. - */ - @java.lang.Override - @java.lang.Deprecated public boolean hasPassword() { - return flowCase_ == 4; - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 - * @return The password. - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow getPassword() { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; - } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; - } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } - - public static final int DEVICE_CODE_FIELD_NUMBER = 5; - /** - *
-   * Configuration for the OAuth Device Code flow.
-   * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - * @return Whether the deviceCode field is set. - */ - @java.lang.Override - public boolean hasDeviceCode() { - return flowCase_ == 5; - } - /** - *
-   * Configuration for the OAuth Device Code flow.
-   * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - * @return The deviceCode. - */ - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() { - if (flowCase_ == 5) { - return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; - } - return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); - } - /** - *
-   * Configuration for the OAuth Device Code flow.
-   * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { - if (flowCase_ == 5) { - return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; - } - return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (flowCase_ == 1) { - output.writeMessage(1, (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_); - } - if (flowCase_ == 2) { - output.writeMessage(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_); - } - if (flowCase_ == 3) { - output.writeMessage(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_); - } - if (flowCase_ == 4) { - output.writeMessage(4, (io.a2a.grpc.PasswordOAuthFlow) flow_); - } - if (flowCase_ == 5) { - output.writeMessage(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (flowCase_ == 1) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_); - } - if (flowCase_ == 2) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_); - } - if (flowCase_ == 3) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, (io.a2a.grpc.ImplicitOAuthFlow) flow_); - } - if (flowCase_ == 4) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, (io.a2a.grpc.PasswordOAuthFlow) flow_); - } - if (flowCase_ == 5) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, (io.a2a.grpc.DeviceCodeOAuthFlow) flow_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.OAuthFlows)) { - return super.equals(obj); - } - io.a2a.grpc.OAuthFlows other = (io.a2a.grpc.OAuthFlows) obj; - - if (!getFlowCase().equals(other.getFlowCase())) return false; - switch (flowCase_) { - case 1: - if (!getAuthorizationCode() - .equals(other.getAuthorizationCode())) return false; - break; - case 2: - if (!getClientCredentials() - .equals(other.getClientCredentials())) return false; - break; - case 3: - if (!getImplicit() - .equals(other.getImplicit())) return false; - break; - case 4: - if (!getPassword() - .equals(other.getPassword())) return false; - break; - case 5: - if (!getDeviceCode() - .equals(other.getDeviceCode())) return false; - break; - case 0: - default: - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - switch (flowCase_) { - case 1: - hash = (37 * hash) + AUTHORIZATION_CODE_FIELD_NUMBER; - hash = (53 * hash) + getAuthorizationCode().hashCode(); - break; - case 2: - hash = (37 * hash) + CLIENT_CREDENTIALS_FIELD_NUMBER; - hash = (53 * hash) + getClientCredentials().hashCode(); - break; - case 3: - hash = (37 * hash) + IMPLICIT_FIELD_NUMBER; - hash = (53 * hash) + getImplicit().hashCode(); - break; - case 4: - hash = (37 * hash) + PASSWORD_FIELD_NUMBER; - hash = (53 * hash) + getPassword().hashCode(); - break; - case 5: - hash = (37 * hash) + DEVICE_CODE_FIELD_NUMBER; - hash = (53 * hash) + getDeviceCode().hashCode(); - break; - case 0: - default: - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.OAuthFlows parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OAuthFlows parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OAuthFlows parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OAuthFlows parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OAuthFlows parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OAuthFlows parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OAuthFlows parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.OAuthFlows parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.OAuthFlows parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.OAuthFlows parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.OAuthFlows parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.OAuthFlows parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.OAuthFlows prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:OAuthFlows]
-   * Defines the configuration for the supported OAuth 2.0 flows.
-   * 
- * - * Protobuf type {@code a2a.v1.OAuthFlows} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.OAuthFlows) - io.a2a.grpc.OAuthFlowsOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.OAuthFlows.class, io.a2a.grpc.OAuthFlows.Builder.class); - } - - // Construct using io.a2a.grpc.OAuthFlows.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - if (authorizationCodeBuilder_ != null) { - authorizationCodeBuilder_.clear(); - } - if (clientCredentialsBuilder_ != null) { - clientCredentialsBuilder_.clear(); - } - if (implicitBuilder_ != null) { - implicitBuilder_.clear(); - } - if (passwordBuilder_ != null) { - passwordBuilder_.clear(); - } - if (deviceCodeBuilder_ != null) { - deviceCodeBuilder_.clear(); - } - flowCase_ = 0; - flow_ = null; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OAuthFlows_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.OAuthFlows getDefaultInstanceForType() { - return io.a2a.grpc.OAuthFlows.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.OAuthFlows build() { - io.a2a.grpc.OAuthFlows result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.OAuthFlows buildPartial() { - io.a2a.grpc.OAuthFlows result = new io.a2a.grpc.OAuthFlows(this); - if (bitField0_ != 0) { buildPartial0(result); } - buildPartialOneofs(result); - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.OAuthFlows result) { - int from_bitField0_ = bitField0_; - } - - private void buildPartialOneofs(io.a2a.grpc.OAuthFlows result) { - result.flowCase_ = flowCase_; - result.flow_ = this.flow_; - if (flowCase_ == 1 && - authorizationCodeBuilder_ != null) { - result.flow_ = authorizationCodeBuilder_.build(); - } - if (flowCase_ == 2 && - clientCredentialsBuilder_ != null) { - result.flow_ = clientCredentialsBuilder_.build(); - } - if (flowCase_ == 3 && - implicitBuilder_ != null) { - result.flow_ = implicitBuilder_.build(); - } - if (flowCase_ == 4 && - passwordBuilder_ != null) { - result.flow_ = passwordBuilder_.build(); - } - if (flowCase_ == 5 && - deviceCodeBuilder_ != null) { - result.flow_ = deviceCodeBuilder_.build(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.OAuthFlows) { - return mergeFrom((io.a2a.grpc.OAuthFlows)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.OAuthFlows other) { - if (other == io.a2a.grpc.OAuthFlows.getDefaultInstance()) return this; - switch (other.getFlowCase()) { - case AUTHORIZATION_CODE: { - mergeAuthorizationCode(other.getAuthorizationCode()); - break; - } - case CLIENT_CREDENTIALS: { - mergeClientCredentials(other.getClientCredentials()); - break; - } - case IMPLICIT: { - mergeImplicit(other.getImplicit()); - break; - } - case PASSWORD: { - mergePassword(other.getPassword()); - break; - } - case DEVICE_CODE: { - mergeDeviceCode(other.getDeviceCode()); - break; - } - case FLOW_NOT_SET: { - break; - } - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - input.readMessage( - internalGetAuthorizationCodeFieldBuilder().getBuilder(), - extensionRegistry); - flowCase_ = 1; - break; - } // case 10 - case 18: { - input.readMessage( - internalGetClientCredentialsFieldBuilder().getBuilder(), - extensionRegistry); - flowCase_ = 2; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetImplicitFieldBuilder().getBuilder(), - extensionRegistry); - flowCase_ = 3; - break; - } // case 26 - case 34: { - input.readMessage( - internalGetPasswordFieldBuilder().getBuilder(), - extensionRegistry); - flowCase_ = 4; - break; - } // case 34 - case 42: { - input.readMessage( - internalGetDeviceCodeFieldBuilder().getBuilder(), - extensionRegistry); - flowCase_ = 5; - break; - } // case 42 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int flowCase_ = 0; - private java.lang.Object flow_; - public FlowCase - getFlowCase() { - return FlowCase.forNumber( - flowCase_); - } - - public Builder clearFlow() { - flowCase_ = 0; - flow_ = null; - onChanged(); - return this; - } - - private int bitField0_; - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthorizationCodeOAuthFlow, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder, io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder> authorizationCodeBuilder_; - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - * @return Whether the authorizationCode field is set. - */ - @java.lang.Override - public boolean hasAuthorizationCode() { - return flowCase_ == 1; - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - * @return The authorizationCode. - */ - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode() { - if (authorizationCodeBuilder_ == null) { - if (flowCase_ == 1) { - return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_; - } - return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); - } else { - if (flowCase_ == 1) { - return authorizationCodeBuilder_.getMessage(); - } - return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); - } - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - public Builder setAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value) { - if (authorizationCodeBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - flow_ = value; - onChanged(); - } else { - authorizationCodeBuilder_.setMessage(value); - } - flowCase_ = 1; - return this; - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - public Builder setAuthorizationCode( - io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder builderForValue) { - if (authorizationCodeBuilder_ == null) { - flow_ = builderForValue.build(); - onChanged(); - } else { - authorizationCodeBuilder_.setMessage(builderForValue.build()); - } - flowCase_ = 1; - return this; - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - public Builder mergeAuthorizationCode(io.a2a.grpc.AuthorizationCodeOAuthFlow value) { - if (authorizationCodeBuilder_ == null) { - if (flowCase_ == 1 && - flow_ != io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance()) { - flow_ = io.a2a.grpc.AuthorizationCodeOAuthFlow.newBuilder((io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_) - .mergeFrom(value).buildPartial(); - } else { - flow_ = value; - } - onChanged(); - } else { - if (flowCase_ == 1) { - authorizationCodeBuilder_.mergeFrom(value); - } else { - authorizationCodeBuilder_.setMessage(value); - } - } - flowCase_ = 1; - return this; - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - public Builder clearAuthorizationCode() { - if (authorizationCodeBuilder_ == null) { - if (flowCase_ == 1) { - flowCase_ = 0; - flow_ = null; - onChanged(); - } - } else { - if (flowCase_ == 1) { - flowCase_ = 0; - flow_ = null; - } - authorizationCodeBuilder_.clear(); - } - return this; - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - public io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder getAuthorizationCodeBuilder() { - return internalGetAuthorizationCodeFieldBuilder().getBuilder(); - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - @java.lang.Override - public io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder() { - if ((flowCase_ == 1) && (authorizationCodeBuilder_ != null)) { - return authorizationCodeBuilder_.getMessageOrBuilder(); - } else { - if (flowCase_ == 1) { - return (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_; - } - return io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); - } - } - /** - *
-     * Configuration for the OAuth Authorization Code flow.
-     * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthorizationCodeOAuthFlow, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder, io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder> - internalGetAuthorizationCodeFieldBuilder() { - if (authorizationCodeBuilder_ == null) { - if (!(flowCase_ == 1)) { - flow_ = io.a2a.grpc.AuthorizationCodeOAuthFlow.getDefaultInstance(); - } - authorizationCodeBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthorizationCodeOAuthFlow, io.a2a.grpc.AuthorizationCodeOAuthFlow.Builder, io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder>( - (io.a2a.grpc.AuthorizationCodeOAuthFlow) flow_, - getParentForChildren(), - isClean()); - flow_ = null; - } - flowCase_ = 1; - onChanged(); - return authorizationCodeBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ClientCredentialsOAuthFlow, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder, io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder> clientCredentialsBuilder_; - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - * @return Whether the clientCredentials field is set. - */ - @java.lang.Override - public boolean hasClientCredentials() { - return flowCase_ == 2; - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - * @return The clientCredentials. - */ - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials() { - if (clientCredentialsBuilder_ == null) { - if (flowCase_ == 2) { - return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_; - } - return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); - } else { - if (flowCase_ == 2) { - return clientCredentialsBuilder_.getMessage(); - } - return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); - } - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - public Builder setClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value) { - if (clientCredentialsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - flow_ = value; - onChanged(); - } else { - clientCredentialsBuilder_.setMessage(value); - } - flowCase_ = 2; - return this; - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - public Builder setClientCredentials( - io.a2a.grpc.ClientCredentialsOAuthFlow.Builder builderForValue) { - if (clientCredentialsBuilder_ == null) { - flow_ = builderForValue.build(); - onChanged(); - } else { - clientCredentialsBuilder_.setMessage(builderForValue.build()); - } - flowCase_ = 2; - return this; - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - public Builder mergeClientCredentials(io.a2a.grpc.ClientCredentialsOAuthFlow value) { - if (clientCredentialsBuilder_ == null) { - if (flowCase_ == 2 && - flow_ != io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance()) { - flow_ = io.a2a.grpc.ClientCredentialsOAuthFlow.newBuilder((io.a2a.grpc.ClientCredentialsOAuthFlow) flow_) - .mergeFrom(value).buildPartial(); - } else { - flow_ = value; - } - onChanged(); - } else { - if (flowCase_ == 2) { - clientCredentialsBuilder_.mergeFrom(value); - } else { - clientCredentialsBuilder_.setMessage(value); - } - } - flowCase_ = 2; - return this; - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - public Builder clearClientCredentials() { - if (clientCredentialsBuilder_ == null) { - if (flowCase_ == 2) { - flowCase_ = 0; - flow_ = null; - onChanged(); - } - } else { - if (flowCase_ == 2) { - flowCase_ = 0; - flow_ = null; - } - clientCredentialsBuilder_.clear(); - } - return this; - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - public io.a2a.grpc.ClientCredentialsOAuthFlow.Builder getClientCredentialsBuilder() { - return internalGetClientCredentialsFieldBuilder().getBuilder(); - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - @java.lang.Override - public io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder() { - if ((flowCase_ == 2) && (clientCredentialsBuilder_ != null)) { - return clientCredentialsBuilder_.getMessageOrBuilder(); - } else { - if (flowCase_ == 2) { - return (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_; - } - return io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); - } - } - /** - *
-     * Configuration for the OAuth Client Credentials flow.
-     * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ClientCredentialsOAuthFlow, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder, io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder> - internalGetClientCredentialsFieldBuilder() { - if (clientCredentialsBuilder_ == null) { - if (!(flowCase_ == 2)) { - flow_ = io.a2a.grpc.ClientCredentialsOAuthFlow.getDefaultInstance(); - } - clientCredentialsBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ClientCredentialsOAuthFlow, io.a2a.grpc.ClientCredentialsOAuthFlow.Builder, io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder>( - (io.a2a.grpc.ClientCredentialsOAuthFlow) flow_, - getParentForChildren(), - isClean()); - flow_ = null; - } - flowCase_ = 2; - onChanged(); - return clientCredentialsBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> implicitBuilder_; - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 - * @return Whether the implicit field is set. - */ - @java.lang.Override - @java.lang.Deprecated public boolean hasImplicit() { - return flowCase_ == 3; - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 - * @return The implicit. - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow getImplicit() { - if (implicitBuilder_ == null) { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } else { - if (flowCase_ == 3) { - return implicitBuilder_.getMessage(); - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Deprecated public Builder setImplicit(io.a2a.grpc.ImplicitOAuthFlow value) { - if (implicitBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - flow_ = value; - onChanged(); - } else { - implicitBuilder_.setMessage(value); - } - flowCase_ = 3; - return this; - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Deprecated public Builder setImplicit( - io.a2a.grpc.ImplicitOAuthFlow.Builder builderForValue) { - if (implicitBuilder_ == null) { - flow_ = builderForValue.build(); - onChanged(); - } else { - implicitBuilder_.setMessage(builderForValue.build()); - } - flowCase_ = 3; - return this; - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Deprecated public Builder mergeImplicit(io.a2a.grpc.ImplicitOAuthFlow value) { - if (implicitBuilder_ == null) { - if (flowCase_ == 3 && - flow_ != io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance()) { - flow_ = io.a2a.grpc.ImplicitOAuthFlow.newBuilder((io.a2a.grpc.ImplicitOAuthFlow) flow_) - .mergeFrom(value).buildPartial(); - } else { - flow_ = value; - } - onChanged(); - } else { - if (flowCase_ == 3) { - implicitBuilder_.mergeFrom(value); - } else { - implicitBuilder_.setMessage(value); - } - } - flowCase_ = 3; - return this; - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Deprecated public Builder clearImplicit() { - if (implicitBuilder_ == null) { - if (flowCase_ == 3) { - flowCase_ = 0; - flow_ = null; - onChanged(); - } - } else { - if (flowCase_ == 3) { - flowCase_ = 0; - flow_ = null; - } - implicitBuilder_.clear(); - } - return this; - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlow.Builder getImplicitBuilder() { - return internalGetImplicitFieldBuilder().getBuilder(); - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder() { - if ((flowCase_ == 3) && (implicitBuilder_ != null)) { - return implicitBuilder_.getMessageOrBuilder(); - } else { - if (flowCase_ == 3) { - return (io.a2a.grpc.ImplicitOAuthFlow) flow_; - } - return io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - } - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder> - internalGetImplicitFieldBuilder() { - if (implicitBuilder_ == null) { - if (!(flowCase_ == 3)) { - flow_ = io.a2a.grpc.ImplicitOAuthFlow.getDefaultInstance(); - } - implicitBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.ImplicitOAuthFlow, io.a2a.grpc.ImplicitOAuthFlow.Builder, io.a2a.grpc.ImplicitOAuthFlowOrBuilder>( - (io.a2a.grpc.ImplicitOAuthFlow) flow_, - getParentForChildren(), - isClean()); - flow_ = null; - } - flowCase_ = 3; - onChanged(); - return implicitBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> passwordBuilder_; - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 - * @return Whether the password field is set. - */ - @java.lang.Override - @java.lang.Deprecated public boolean hasPassword() { - return flowCase_ == 4; - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 - * @return The password. - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow getPassword() { - if (passwordBuilder_ == null) { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; - } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } else { - if (flowCase_ == 4) { - return passwordBuilder_.getMessage(); - } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Deprecated public Builder setPassword(io.a2a.grpc.PasswordOAuthFlow value) { - if (passwordBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - flow_ = value; - onChanged(); - } else { - passwordBuilder_.setMessage(value); - } - flowCase_ = 4; - return this; - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Deprecated public Builder setPassword( - io.a2a.grpc.PasswordOAuthFlow.Builder builderForValue) { - if (passwordBuilder_ == null) { - flow_ = builderForValue.build(); - onChanged(); - } else { - passwordBuilder_.setMessage(builderForValue.build()); - } - flowCase_ = 4; - return this; - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Deprecated public Builder mergePassword(io.a2a.grpc.PasswordOAuthFlow value) { - if (passwordBuilder_ == null) { - if (flowCase_ == 4 && - flow_ != io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) { - flow_ = io.a2a.grpc.PasswordOAuthFlow.newBuilder((io.a2a.grpc.PasswordOAuthFlow) flow_) - .mergeFrom(value).buildPartial(); - } else { - flow_ = value; - } - onChanged(); - } else { - if (flowCase_ == 4) { - passwordBuilder_.mergeFrom(value); - } else { - passwordBuilder_.setMessage(value); - } - } - flowCase_ = 4; - return this; - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Deprecated public Builder clearPassword() { - if (passwordBuilder_ == null) { - if (flowCase_ == 4) { - flowCase_ = 0; - flow_ = null; - onChanged(); - } - } else { - if (flowCase_ == 4) { - flowCase_ = 0; - flow_ = null; - } - passwordBuilder_.clear(); - } - return this; - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlow.Builder getPasswordBuilder() { - return internalGetPasswordFieldBuilder().getBuilder(); - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Override - @java.lang.Deprecated public io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder() { - if ((flowCase_ == 4) && (passwordBuilder_ != null)) { - return passwordBuilder_.getMessageOrBuilder(); - } else { - if (flowCase_ == 4) { - return (io.a2a.grpc.PasswordOAuthFlow) flow_; - } - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } - } - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder> - internalGetPasswordFieldBuilder() { - if (passwordBuilder_ == null) { - if (!(flowCase_ == 4)) { - flow_ = io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } - passwordBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PasswordOAuthFlow, io.a2a.grpc.PasswordOAuthFlow.Builder, io.a2a.grpc.PasswordOAuthFlowOrBuilder>( - (io.a2a.grpc.PasswordOAuthFlow) flow_, - getParentForChildren(), - isClean()); - flow_ = null; - } - flowCase_ = 4; - onChanged(); - return passwordBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> deviceCodeBuilder_; - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - * @return Whether the deviceCode field is set. - */ - @java.lang.Override - public boolean hasDeviceCode() { - return flowCase_ == 5; - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - * @return The deviceCode. - */ - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode() { - if (deviceCodeBuilder_ == null) { - if (flowCase_ == 5) { - return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; - } - return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); - } else { - if (flowCase_ == 5) { - return deviceCodeBuilder_.getMessage(); - } - return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); - } - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - public Builder setDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { - if (deviceCodeBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - flow_ = value; - onChanged(); - } else { - deviceCodeBuilder_.setMessage(value); - } - flowCase_ = 5; - return this; - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - public Builder setDeviceCode( - io.a2a.grpc.DeviceCodeOAuthFlow.Builder builderForValue) { - if (deviceCodeBuilder_ == null) { - flow_ = builderForValue.build(); - onChanged(); - } else { - deviceCodeBuilder_.setMessage(builderForValue.build()); - } - flowCase_ = 5; - return this; - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - public Builder mergeDeviceCode(io.a2a.grpc.DeviceCodeOAuthFlow value) { - if (deviceCodeBuilder_ == null) { - if (flowCase_ == 5 && - flow_ != io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance()) { - flow_ = io.a2a.grpc.DeviceCodeOAuthFlow.newBuilder((io.a2a.grpc.DeviceCodeOAuthFlow) flow_) - .mergeFrom(value).buildPartial(); - } else { - flow_ = value; - } - onChanged(); - } else { - if (flowCase_ == 5) { - deviceCodeBuilder_.mergeFrom(value); - } else { - deviceCodeBuilder_.setMessage(value); - } - } - flowCase_ = 5; - return this; - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - public Builder clearDeviceCode() { - if (deviceCodeBuilder_ == null) { - if (flowCase_ == 5) { - flowCase_ = 0; - flow_ = null; - onChanged(); - } - } else { - if (flowCase_ == 5) { - flowCase_ = 0; - flow_ = null; - } - deviceCodeBuilder_.clear(); - } - return this; - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - public io.a2a.grpc.DeviceCodeOAuthFlow.Builder getDeviceCodeBuilder() { - return internalGetDeviceCodeFieldBuilder().getBuilder(); - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - @java.lang.Override - public io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder() { - if ((flowCase_ == 5) && (deviceCodeBuilder_ != null)) { - return deviceCodeBuilder_.getMessageOrBuilder(); - } else { - if (flowCase_ == 5) { - return (io.a2a.grpc.DeviceCodeOAuthFlow) flow_; - } - return io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); - } - } - /** - *
-     * Configuration for the OAuth Device Code flow.
-     * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder> - internalGetDeviceCodeFieldBuilder() { - if (deviceCodeBuilder_ == null) { - if (!(flowCase_ == 5)) { - flow_ = io.a2a.grpc.DeviceCodeOAuthFlow.getDefaultInstance(); - } - deviceCodeBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.DeviceCodeOAuthFlow, io.a2a.grpc.DeviceCodeOAuthFlow.Builder, io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder>( - (io.a2a.grpc.DeviceCodeOAuthFlow) flow_, - getParentForChildren(), - isClean()); - flow_ = null; - } - flowCase_ = 5; - onChanged(); - return deviceCodeBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.OAuthFlows) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.OAuthFlows) - private static final io.a2a.grpc.OAuthFlows DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.OAuthFlows(); - } - - public static io.a2a.grpc.OAuthFlows getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public OAuthFlows parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.OAuthFlows getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java deleted file mode 100644 index 1debd6d12..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/OAuthFlowsOrBuilder.java +++ /dev/null @@ -1,133 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface OAuthFlowsOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.OAuthFlows) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Configuration for the OAuth Authorization Code flow.
-   * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - * @return Whether the authorizationCode field is set. - */ - boolean hasAuthorizationCode(); - /** - *
-   * Configuration for the OAuth Authorization Code flow.
-   * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - * @return The authorizationCode. - */ - io.a2a.grpc.AuthorizationCodeOAuthFlow getAuthorizationCode(); - /** - *
-   * Configuration for the OAuth Authorization Code flow.
-   * 
- * - * .a2a.v1.AuthorizationCodeOAuthFlow authorization_code = 1; - */ - io.a2a.grpc.AuthorizationCodeOAuthFlowOrBuilder getAuthorizationCodeOrBuilder(); - - /** - *
-   * Configuration for the OAuth Client Credentials flow.
-   * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - * @return Whether the clientCredentials field is set. - */ - boolean hasClientCredentials(); - /** - *
-   * Configuration for the OAuth Client Credentials flow.
-   * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - * @return The clientCredentials. - */ - io.a2a.grpc.ClientCredentialsOAuthFlow getClientCredentials(); - /** - *
-   * Configuration for the OAuth Client Credentials flow.
-   * 
- * - * .a2a.v1.ClientCredentialsOAuthFlow client_credentials = 2; - */ - io.a2a.grpc.ClientCredentialsOAuthFlowOrBuilder getClientCredentialsOrBuilder(); - - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 - * @return Whether the implicit field is set. - */ - @java.lang.Deprecated boolean hasImplicit(); - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.implicit is deprecated. - * See a2a.proto;l=633 - * @return The implicit. - */ - @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlow getImplicit(); - /** - * .a2a.v1.ImplicitOAuthFlow implicit = 3 [deprecated = true]; - */ - @java.lang.Deprecated io.a2a.grpc.ImplicitOAuthFlowOrBuilder getImplicitOrBuilder(); - - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 - * @return Whether the password field is set. - */ - @java.lang.Deprecated boolean hasPassword(); - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - * @deprecated a2a.v1.OAuthFlows.password is deprecated. - * See a2a.proto;l=634 - * @return The password. - */ - @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlow getPassword(); - /** - * .a2a.v1.PasswordOAuthFlow password = 4 [deprecated = true]; - */ - @java.lang.Deprecated io.a2a.grpc.PasswordOAuthFlowOrBuilder getPasswordOrBuilder(); - - /** - *
-   * Configuration for the OAuth Device Code flow.
-   * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - * @return Whether the deviceCode field is set. - */ - boolean hasDeviceCode(); - /** - *
-   * Configuration for the OAuth Device Code flow.
-   * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - * @return The deviceCode. - */ - io.a2a.grpc.DeviceCodeOAuthFlow getDeviceCode(); - /** - *
-   * Configuration for the OAuth Device Code flow.
-   * 
- * - * .a2a.v1.DeviceCodeOAuthFlow device_code = 5; - */ - io.a2a.grpc.DeviceCodeOAuthFlowOrBuilder getDeviceCodeOrBuilder(); - - io.a2a.grpc.OAuthFlows.FlowCase getFlowCase(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java deleted file mode 100644 index 001ea51e8..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecurityScheme.java +++ /dev/null @@ -1,711 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:OpenIdConnectSecurityScheme]
- * Defines a security scheme using OpenID Connect.
- * 
- * - * Protobuf type {@code a2a.v1.OpenIdConnectSecurityScheme} - */ -@com.google.protobuf.Generated -public final class OpenIdConnectSecurityScheme extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.OpenIdConnectSecurityScheme) - OpenIdConnectSecuritySchemeOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "OpenIdConnectSecurityScheme"); - } - // Use OpenIdConnectSecurityScheme.newBuilder() to construct. - private OpenIdConnectSecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private OpenIdConnectSecurityScheme() { - description_ = ""; - openIdConnectUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.OpenIdConnectSecurityScheme.class, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder.class); - } - - public static final int DESCRIPTION_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object description_ = ""; - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - @java.lang.Override - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } - } - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int OPEN_ID_CONNECT_URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object openIdConnectUrl_ = ""; - /** - *
-   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-   * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The openIdConnectUrl. - */ - @java.lang.Override - public java.lang.String getOpenIdConnectUrl() { - java.lang.Object ref = openIdConnectUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - openIdConnectUrl_ = s; - return s; - } - } - /** - *
-   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-   * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for openIdConnectUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getOpenIdConnectUrlBytes() { - java.lang.Object ref = openIdConnectUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - openIdConnectUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, description_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(openIdConnectUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, openIdConnectUrl_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(description_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, description_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(openIdConnectUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, openIdConnectUrl_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.OpenIdConnectSecurityScheme)) { - return super.equals(obj); - } - io.a2a.grpc.OpenIdConnectSecurityScheme other = (io.a2a.grpc.OpenIdConnectSecurityScheme) obj; - - if (!getDescription() - .equals(other.getDescription())) return false; - if (!getOpenIdConnectUrl() - .equals(other.getOpenIdConnectUrl())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + DESCRIPTION_FIELD_NUMBER; - hash = (53 * hash) + getDescription().hashCode(); - hash = (37 * hash) + OPEN_ID_CONNECT_URL_FIELD_NUMBER; - hash = (53 * hash) + getOpenIdConnectUrl().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.OpenIdConnectSecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.OpenIdConnectSecurityScheme prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:OpenIdConnectSecurityScheme]
-   * Defines a security scheme using OpenID Connect.
-   * 
- * - * Protobuf type {@code a2a.v1.OpenIdConnectSecurityScheme} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.OpenIdConnectSecurityScheme) - io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.OpenIdConnectSecurityScheme.class, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder.class); - } - - // Construct using io.a2a.grpc.OpenIdConnectSecurityScheme.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - description_ = ""; - openIdConnectUrl_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_OpenIdConnectSecurityScheme_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() { - return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecurityScheme build() { - io.a2a.grpc.OpenIdConnectSecurityScheme result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecurityScheme buildPartial() { - io.a2a.grpc.OpenIdConnectSecurityScheme result = new io.a2a.grpc.OpenIdConnectSecurityScheme(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.OpenIdConnectSecurityScheme result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.description_ = description_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.openIdConnectUrl_ = openIdConnectUrl_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.OpenIdConnectSecurityScheme) { - return mergeFrom((io.a2a.grpc.OpenIdConnectSecurityScheme)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.OpenIdConnectSecurityScheme other) { - if (other == io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) return this; - if (!other.getDescription().isEmpty()) { - description_ = other.description_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getOpenIdConnectUrl().isEmpty()) { - openIdConnectUrl_ = other.openIdConnectUrl_; - bitField0_ |= 0x00000002; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - description_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - openIdConnectUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object description_ = ""; - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The description. - */ - public java.lang.String getDescription() { - java.lang.Object ref = description_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - description_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return The bytes for description. - */ - public com.google.protobuf.ByteString - getDescriptionBytes() { - java.lang.Object ref = description_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - description_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The description to set. - * @return This builder for chaining. - */ - public Builder setDescription( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @return This builder for chaining. - */ - public Builder clearDescription() { - description_ = getDefaultInstance().getDescription(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * An optional description for the security scheme.
-     * 
- * - * string description = 1; - * @param value The bytes for description to set. - * @return This builder for chaining. - */ - public Builder setDescriptionBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - description_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object openIdConnectUrl_ = ""; - /** - *
-     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-     * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The openIdConnectUrl. - */ - public java.lang.String getOpenIdConnectUrl() { - java.lang.Object ref = openIdConnectUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - openIdConnectUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-     * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for openIdConnectUrl. - */ - public com.google.protobuf.ByteString - getOpenIdConnectUrlBytes() { - java.lang.Object ref = openIdConnectUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - openIdConnectUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-     * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The openIdConnectUrl to set. - * @return This builder for chaining. - */ - public Builder setOpenIdConnectUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - openIdConnectUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-     * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearOpenIdConnectUrl() { - openIdConnectUrl_ = getDefaultInstance().getOpenIdConnectUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-     * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-     * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for openIdConnectUrl to set. - * @return This builder for chaining. - */ - public Builder setOpenIdConnectUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - openIdConnectUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.OpenIdConnectSecurityScheme) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.OpenIdConnectSecurityScheme) - private static final io.a2a.grpc.OpenIdConnectSecurityScheme DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.OpenIdConnectSecurityScheme(); - } - - public static io.a2a.grpc.OpenIdConnectSecurityScheme getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public OpenIdConnectSecurityScheme parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecurityScheme getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java deleted file mode 100644 index d51225f03..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/OpenIdConnectSecuritySchemeOrBuilder.java +++ /dev/null @@ -1,54 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface OpenIdConnectSecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.OpenIdConnectSecurityScheme) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The description. - */ - java.lang.String getDescription(); - /** - *
-   * An optional description for the security scheme.
-   * 
- * - * string description = 1; - * @return The bytes for description. - */ - com.google.protobuf.ByteString - getDescriptionBytes(); - - /** - *
-   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-   * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The openIdConnectUrl. - */ - java.lang.String getOpenIdConnectUrl(); - /** - *
-   * The OpenID Connect Discovery URL for the OIDC provider's metadata.
-   * See: https://openid.net/specs/openid-connect-discovery-1_0.html
-   * 
- * - * string open_id_connect_url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for openIdConnectUrl. - */ - com.google.protobuf.ByteString - getOpenIdConnectUrlBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Part.java b/spec-grpc/src/main/java/io/a2a/grpc/Part.java deleted file mode 100644 index 879380c96..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/Part.java +++ /dev/null @@ -1,1820 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:Part]
- * Part represents a container for a section of communication content.
- * Parts can be purely textual, some sort of file (image, video, etc) or
- * a structured data blob (i.e. JSON).
- * 
- * - * Protobuf type {@code a2a.v1.Part} - */ -@com.google.protobuf.Generated -public final class Part extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Part) - PartOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "Part"); - } - // Use Part.newBuilder() to construct. - private Part(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private Part() { - filename_ = ""; - mediaType_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Part.class, io.a2a.grpc.Part.Builder.class); - } - - private int bitField0_; - private int contentCase_ = 0; - @SuppressWarnings("serial") - private java.lang.Object content_; - public enum ContentCase - implements com.google.protobuf.Internal.EnumLite, - com.google.protobuf.AbstractMessage.InternalOneOfEnum { - TEXT(1), - RAW(2), - URL(3), - DATA(4), - CONTENT_NOT_SET(0); - private final int value; - private ContentCase(int value) { - this.value = value; - } - /** - * @param value The number of the enum to look for. - * @return The enum associated with the given number. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static ContentCase valueOf(int value) { - return forNumber(value); - } - - public static ContentCase forNumber(int value) { - switch (value) { - case 1: return TEXT; - case 2: return RAW; - case 3: return URL; - case 4: return DATA; - case 0: return CONTENT_NOT_SET; - default: return null; - } - } - public int getNumber() { - return this.value; - } - }; - - public ContentCase - getContentCase() { - return ContentCase.forNumber( - contentCase_); - } - - public static final int TEXT_FIELD_NUMBER = 1; - /** - *
-   * The string content of the text part.
-   * 
- * - * string text = 1; - * @return Whether the text field is set. - */ - public boolean hasText() { - return contentCase_ == 1; - } - /** - *
-   * The string content of the text part.
-   * 
- * - * string text = 1; - * @return The text. - */ - public java.lang.String getText() { - java.lang.Object ref = ""; - if (contentCase_ == 1) { - ref = content_; - } - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (contentCase_ == 1) { - content_ = s; - } - return s; - } - } - /** - *
-   * The string content of the text part.
-   * 
- * - * string text = 1; - * @return The bytes for text. - */ - public com.google.protobuf.ByteString - getTextBytes() { - java.lang.Object ref = ""; - if (contentCase_ == 1) { - ref = content_; - } - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - if (contentCase_ == 1) { - content_ = b; - } - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int RAW_FIELD_NUMBER = 2; - /** - *
-   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-   * 
- * - * bytes raw = 2; - * @return Whether the raw field is set. - */ - @java.lang.Override - public boolean hasRaw() { - return contentCase_ == 2; - } - /** - *
-   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-   * 
- * - * bytes raw = 2; - * @return The raw. - */ - @java.lang.Override - public com.google.protobuf.ByteString getRaw() { - if (contentCase_ == 2) { - return (com.google.protobuf.ByteString) content_; - } - return com.google.protobuf.ByteString.EMPTY; - } - - public static final int URL_FIELD_NUMBER = 3; - /** - *
-   * A URL pointing to the file's content.
-   * 
- * - * string url = 3; - * @return Whether the url field is set. - */ - public boolean hasUrl() { - return contentCase_ == 3; - } - /** - *
-   * A URL pointing to the file's content.
-   * 
- * - * string url = 3; - * @return The url. - */ - public java.lang.String getUrl() { - java.lang.Object ref = ""; - if (contentCase_ == 3) { - ref = content_; - } - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (contentCase_ == 3) { - content_ = s; - } - return s; - } - } - /** - *
-   * A URL pointing to the file's content.
-   * 
- * - * string url = 3; - * @return The bytes for url. - */ - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = ""; - if (contentCase_ == 3) { - ref = content_; - } - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - if (contentCase_ == 3) { - content_ = b; - } - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int DATA_FIELD_NUMBER = 4; - /** - *
-   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-   * 
- * - * .google.protobuf.Value data = 4; - * @return Whether the data field is set. - */ - @java.lang.Override - public boolean hasData() { - return contentCase_ == 4; - } - /** - *
-   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-   * 
- * - * .google.protobuf.Value data = 4; - * @return The data. - */ - @java.lang.Override - public com.google.protobuf.Value getData() { - if (contentCase_ == 4) { - return (com.google.protobuf.Value) content_; - } - return com.google.protobuf.Value.getDefaultInstance(); - } - /** - *
-   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-   * 
- * - * .google.protobuf.Value data = 4; - */ - @java.lang.Override - public com.google.protobuf.ValueOrBuilder getDataOrBuilder() { - if (contentCase_ == 4) { - return (com.google.protobuf.Value) content_; - } - return com.google.protobuf.Value.getDefaultInstance(); - } - - public static final int METADATA_FIELD_NUMBER = 5; - private com.google.protobuf.Struct metadata_; - /** - *
-   * Optional metadata associated with this part.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return Whether the metadata field is set. - */ - @java.lang.Override - public boolean hasMetadata() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * Optional metadata associated with this part.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return The metadata. - */ - @java.lang.Override - public com.google.protobuf.Struct getMetadata() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - /** - *
-   * Optional metadata associated with this part.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - - public static final int FILENAME_FIELD_NUMBER = 6; - @SuppressWarnings("serial") - private volatile java.lang.Object filename_ = ""; - /** - *
-   * An optional name for the file (e.g., "document.pdf").
-   * 
- * - * string filename = 6; - * @return The filename. - */ - @java.lang.Override - public java.lang.String getFilename() { - java.lang.Object ref = filename_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - filename_ = s; - return s; - } - } - /** - *
-   * An optional name for the file (e.g., "document.pdf").
-   * 
- * - * string filename = 6; - * @return The bytes for filename. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getFilenameBytes() { - java.lang.Object ref = filename_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - filename_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int MEDIA_TYPE_FIELD_NUMBER = 7; - @SuppressWarnings("serial") - private volatile java.lang.Object mediaType_ = ""; - /** - *
-   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-   * This field is available for all part types.
-   * 
- * - * string media_type = 7; - * @return The mediaType. - */ - @java.lang.Override - public java.lang.String getMediaType() { - java.lang.Object ref = mediaType_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - mediaType_ = s; - return s; - } - } - /** - *
-   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-   * This field is available for all part types.
-   * 
- * - * string media_type = 7; - * @return The bytes for mediaType. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getMediaTypeBytes() { - java.lang.Object ref = mediaType_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - mediaType_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (contentCase_ == 1) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, content_); - } - if (contentCase_ == 2) { - output.writeBytes( - 2, (com.google.protobuf.ByteString) content_); - } - if (contentCase_ == 3) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, content_); - } - if (contentCase_ == 4) { - output.writeMessage(4, (com.google.protobuf.Value) content_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(5, getMetadata()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(filename_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 6, filename_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mediaType_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 7, mediaType_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (contentCase_ == 1) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, content_); - } - if (contentCase_ == 2) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize( - 2, (com.google.protobuf.ByteString) content_); - } - if (contentCase_ == 3) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, content_); - } - if (contentCase_ == 4) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, (com.google.protobuf.Value) content_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, getMetadata()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(filename_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(6, filename_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(mediaType_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(7, mediaType_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.Part)) { - return super.equals(obj); - } - io.a2a.grpc.Part other = (io.a2a.grpc.Part) obj; - - if (hasMetadata() != other.hasMetadata()) return false; - if (hasMetadata()) { - if (!getMetadata() - .equals(other.getMetadata())) return false; - } - if (!getFilename() - .equals(other.getFilename())) return false; - if (!getMediaType() - .equals(other.getMediaType())) return false; - if (!getContentCase().equals(other.getContentCase())) return false; - switch (contentCase_) { - case 1: - if (!getText() - .equals(other.getText())) return false; - break; - case 2: - if (!getRaw() - .equals(other.getRaw())) return false; - break; - case 3: - if (!getUrl() - .equals(other.getUrl())) return false; - break; - case 4: - if (!getData() - .equals(other.getData())) return false; - break; - case 0: - default: - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (hasMetadata()) { - hash = (37 * hash) + METADATA_FIELD_NUMBER; - hash = (53 * hash) + getMetadata().hashCode(); - } - hash = (37 * hash) + FILENAME_FIELD_NUMBER; - hash = (53 * hash) + getFilename().hashCode(); - hash = (37 * hash) + MEDIA_TYPE_FIELD_NUMBER; - hash = (53 * hash) + getMediaType().hashCode(); - switch (contentCase_) { - case 1: - hash = (37 * hash) + TEXT_FIELD_NUMBER; - hash = (53 * hash) + getText().hashCode(); - break; - case 2: - hash = (37 * hash) + RAW_FIELD_NUMBER; - hash = (53 * hash) + getRaw().hashCode(); - break; - case 3: - hash = (37 * hash) + URL_FIELD_NUMBER; - hash = (53 * hash) + getUrl().hashCode(); - break; - case 4: - hash = (37 * hash) + DATA_FIELD_NUMBER; - hash = (53 * hash) + getData().hashCode(); - break; - case 0: - default: - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.Part parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Part parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Part parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Part parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Part parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Part parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Part parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Part parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.Part parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.Part parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.Part parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Part parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.Part prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:Part]
-   * Part represents a container for a section of communication content.
-   * Parts can be purely textual, some sort of file (image, video, etc) or
-   * a structured data blob (i.e. JSON).
-   * 
- * - * Protobuf type {@code a2a.v1.Part} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Part) - io.a2a.grpc.PartOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Part.class, io.a2a.grpc.Part.Builder.class); - } - - // Construct using io.a2a.grpc.Part.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetMetadataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - if (dataBuilder_ != null) { - dataBuilder_.clear(); - } - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - filename_ = ""; - mediaType_ = ""; - contentCase_ = 0; - content_ = null; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Part_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.Part getDefaultInstanceForType() { - return io.a2a.grpc.Part.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.Part build() { - io.a2a.grpc.Part result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.Part buildPartial() { - io.a2a.grpc.Part result = new io.a2a.grpc.Part(this); - if (bitField0_ != 0) { buildPartial0(result); } - buildPartialOneofs(result); - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.Part result) { - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000010) != 0)) { - result.metadata_ = metadataBuilder_ == null - ? metadata_ - : metadataBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000020) != 0)) { - result.filename_ = filename_; - } - if (((from_bitField0_ & 0x00000040) != 0)) { - result.mediaType_ = mediaType_; - } - result.bitField0_ |= to_bitField0_; - } - - private void buildPartialOneofs(io.a2a.grpc.Part result) { - result.contentCase_ = contentCase_; - result.content_ = this.content_; - if (contentCase_ == 4 && - dataBuilder_ != null) { - result.content_ = dataBuilder_.build(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.Part) { - return mergeFrom((io.a2a.grpc.Part)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.Part other) { - if (other == io.a2a.grpc.Part.getDefaultInstance()) return this; - if (other.hasMetadata()) { - mergeMetadata(other.getMetadata()); - } - if (!other.getFilename().isEmpty()) { - filename_ = other.filename_; - bitField0_ |= 0x00000020; - onChanged(); - } - if (!other.getMediaType().isEmpty()) { - mediaType_ = other.mediaType_; - bitField0_ |= 0x00000040; - onChanged(); - } - switch (other.getContentCase()) { - case TEXT: { - contentCase_ = 1; - content_ = other.content_; - onChanged(); - break; - } - case RAW: { - setRaw(other.getRaw()); - break; - } - case URL: { - contentCase_ = 3; - content_ = other.content_; - onChanged(); - break; - } - case DATA: { - mergeData(other.getData()); - break; - } - case CONTENT_NOT_SET: { - break; - } - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - java.lang.String s = input.readStringRequireUtf8(); - contentCase_ = 1; - content_ = s; - break; - } // case 10 - case 18: { - content_ = input.readBytes(); - contentCase_ = 2; - break; - } // case 18 - case 26: { - java.lang.String s = input.readStringRequireUtf8(); - contentCase_ = 3; - content_ = s; - break; - } // case 26 - case 34: { - input.readMessage( - internalGetDataFieldBuilder().getBuilder(), - extensionRegistry); - contentCase_ = 4; - break; - } // case 34 - case 42: { - input.readMessage( - internalGetMetadataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000010; - break; - } // case 42 - case 50: { - filename_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000020; - break; - } // case 50 - case 58: { - mediaType_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000040; - break; - } // case 58 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int contentCase_ = 0; - private java.lang.Object content_; - public ContentCase - getContentCase() { - return ContentCase.forNumber( - contentCase_); - } - - public Builder clearContent() { - contentCase_ = 0; - content_ = null; - onChanged(); - return this; - } - - private int bitField0_; - - /** - *
-     * The string content of the text part.
-     * 
- * - * string text = 1; - * @return Whether the text field is set. - */ - @java.lang.Override - public boolean hasText() { - return contentCase_ == 1; - } - /** - *
-     * The string content of the text part.
-     * 
- * - * string text = 1; - * @return The text. - */ - @java.lang.Override - public java.lang.String getText() { - java.lang.Object ref = ""; - if (contentCase_ == 1) { - ref = content_; - } - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (contentCase_ == 1) { - content_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The string content of the text part.
-     * 
- * - * string text = 1; - * @return The bytes for text. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTextBytes() { - java.lang.Object ref = ""; - if (contentCase_ == 1) { - ref = content_; - } - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - if (contentCase_ == 1) { - content_ = b; - } - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The string content of the text part.
-     * 
- * - * string text = 1; - * @param value The text to set. - * @return This builder for chaining. - */ - public Builder setText( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - contentCase_ = 1; - content_ = value; - onChanged(); - return this; - } - /** - *
-     * The string content of the text part.
-     * 
- * - * string text = 1; - * @return This builder for chaining. - */ - public Builder clearText() { - if (contentCase_ == 1) { - contentCase_ = 0; - content_ = null; - onChanged(); - } - return this; - } - /** - *
-     * The string content of the text part.
-     * 
- * - * string text = 1; - * @param value The bytes for text to set. - * @return This builder for chaining. - */ - public Builder setTextBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - contentCase_ = 1; - content_ = value; - onChanged(); - return this; - } - - /** - *
-     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-     * 
- * - * bytes raw = 2; - * @return Whether the raw field is set. - */ - public boolean hasRaw() { - return contentCase_ == 2; - } - /** - *
-     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-     * 
- * - * bytes raw = 2; - * @return The raw. - */ - public com.google.protobuf.ByteString getRaw() { - if (contentCase_ == 2) { - return (com.google.protobuf.ByteString) content_; - } - return com.google.protobuf.ByteString.EMPTY; - } - /** - *
-     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-     * 
- * - * bytes raw = 2; - * @param value The raw to set. - * @return This builder for chaining. - */ - public Builder setRaw(com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - contentCase_ = 2; - content_ = value; - onChanged(); - return this; - } - /** - *
-     * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-     * 
- * - * bytes raw = 2; - * @return This builder for chaining. - */ - public Builder clearRaw() { - if (contentCase_ == 2) { - contentCase_ = 0; - content_ = null; - onChanged(); - } - return this; - } - - /** - *
-     * A URL pointing to the file's content.
-     * 
- * - * string url = 3; - * @return Whether the url field is set. - */ - @java.lang.Override - public boolean hasUrl() { - return contentCase_ == 3; - } - /** - *
-     * A URL pointing to the file's content.
-     * 
- * - * string url = 3; - * @return The url. - */ - @java.lang.Override - public java.lang.String getUrl() { - java.lang.Object ref = ""; - if (contentCase_ == 3) { - ref = content_; - } - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (contentCase_ == 3) { - content_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A URL pointing to the file's content.
-     * 
- * - * string url = 3; - * @return The bytes for url. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = ""; - if (contentCase_ == 3) { - ref = content_; - } - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - if (contentCase_ == 3) { - content_ = b; - } - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A URL pointing to the file's content.
-     * 
- * - * string url = 3; - * @param value The url to set. - * @return This builder for chaining. - */ - public Builder setUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - contentCase_ = 3; - content_ = value; - onChanged(); - return this; - } - /** - *
-     * A URL pointing to the file's content.
-     * 
- * - * string url = 3; - * @return This builder for chaining. - */ - public Builder clearUrl() { - if (contentCase_ == 3) { - contentCase_ = 0; - content_ = null; - onChanged(); - } - return this; - } - /** - *
-     * A URL pointing to the file's content.
-     * 
- * - * string url = 3; - * @param value The bytes for url to set. - * @return This builder for chaining. - */ - public Builder setUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - contentCase_ = 3; - content_ = value; - onChanged(); - return this; - } - - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Value, com.google.protobuf.Value.Builder, com.google.protobuf.ValueOrBuilder> dataBuilder_; - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - * @return Whether the data field is set. - */ - @java.lang.Override - public boolean hasData() { - return contentCase_ == 4; - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - * @return The data. - */ - @java.lang.Override - public com.google.protobuf.Value getData() { - if (dataBuilder_ == null) { - if (contentCase_ == 4) { - return (com.google.protobuf.Value) content_; - } - return com.google.protobuf.Value.getDefaultInstance(); - } else { - if (contentCase_ == 4) { - return dataBuilder_.getMessage(); - } - return com.google.protobuf.Value.getDefaultInstance(); - } - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - */ - public Builder setData(com.google.protobuf.Value value) { - if (dataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - content_ = value; - onChanged(); - } else { - dataBuilder_.setMessage(value); - } - contentCase_ = 4; - return this; - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - */ - public Builder setData( - com.google.protobuf.Value.Builder builderForValue) { - if (dataBuilder_ == null) { - content_ = builderForValue.build(); - onChanged(); - } else { - dataBuilder_.setMessage(builderForValue.build()); - } - contentCase_ = 4; - return this; - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - */ - public Builder mergeData(com.google.protobuf.Value value) { - if (dataBuilder_ == null) { - if (contentCase_ == 4 && - content_ != com.google.protobuf.Value.getDefaultInstance()) { - content_ = com.google.protobuf.Value.newBuilder((com.google.protobuf.Value) content_) - .mergeFrom(value).buildPartial(); - } else { - content_ = value; - } - onChanged(); - } else { - if (contentCase_ == 4) { - dataBuilder_.mergeFrom(value); - } else { - dataBuilder_.setMessage(value); - } - } - contentCase_ = 4; - return this; - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - */ - public Builder clearData() { - if (dataBuilder_ == null) { - if (contentCase_ == 4) { - contentCase_ = 0; - content_ = null; - onChanged(); - } - } else { - if (contentCase_ == 4) { - contentCase_ = 0; - content_ = null; - } - dataBuilder_.clear(); - } - return this; - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - */ - public com.google.protobuf.Value.Builder getDataBuilder() { - return internalGetDataFieldBuilder().getBuilder(); - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - */ - @java.lang.Override - public com.google.protobuf.ValueOrBuilder getDataOrBuilder() { - if ((contentCase_ == 4) && (dataBuilder_ != null)) { - return dataBuilder_.getMessageOrBuilder(); - } else { - if (contentCase_ == 4) { - return (com.google.protobuf.Value) content_; - } - return com.google.protobuf.Value.getDefaultInstance(); - } - } - /** - *
-     * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-     * 
- * - * .google.protobuf.Value data = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Value, com.google.protobuf.Value.Builder, com.google.protobuf.ValueOrBuilder> - internalGetDataFieldBuilder() { - if (dataBuilder_ == null) { - if (!(contentCase_ == 4)) { - content_ = com.google.protobuf.Value.getDefaultInstance(); - } - dataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Value, com.google.protobuf.Value.Builder, com.google.protobuf.ValueOrBuilder>( - (com.google.protobuf.Value) content_, - getParentForChildren(), - isClean()); - content_ = null; - } - contentCase_ = 4; - onChanged(); - return dataBuilder_; - } - - private com.google.protobuf.Struct metadata_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - * @return Whether the metadata field is set. - */ - public boolean hasMetadata() { - return ((bitField0_ & 0x00000010) != 0); - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - * @return The metadata. - */ - public com.google.protobuf.Struct getMetadata() { - if (metadataBuilder_ == null) { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } else { - return metadataBuilder_.getMessage(); - } - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder setMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - metadata_ = value; - } else { - metadataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder setMetadata( - com.google.protobuf.Struct.Builder builderForValue) { - if (metadataBuilder_ == null) { - metadata_ = builderForValue.build(); - } else { - metadataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder mergeMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000010) != 0) && - metadata_ != null && - metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { - getMetadataBuilder().mergeFrom(value); - } else { - metadata_ = value; - } - } else { - metadataBuilder_.mergeFrom(value); - } - if (metadata_ != null) { - bitField0_ |= 0x00000010; - onChanged(); - } - return this; - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000010); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000010; - onChanged(); - return internalGetMetadataFieldBuilder().getBuilder(); - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - if (metadataBuilder_ != null) { - return metadataBuilder_.getMessageOrBuilder(); - } else { - return metadata_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - } - /** - *
-     * Optional metadata associated with this part.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetMetadataFieldBuilder() { - if (metadataBuilder_ == null) { - metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getMetadata(), - getParentForChildren(), - isClean()); - metadata_ = null; - } - return metadataBuilder_; - } - - private java.lang.Object filename_ = ""; - /** - *
-     * An optional name for the file (e.g., "document.pdf").
-     * 
- * - * string filename = 6; - * @return The filename. - */ - public java.lang.String getFilename() { - java.lang.Object ref = filename_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - filename_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * An optional name for the file (e.g., "document.pdf").
-     * 
- * - * string filename = 6; - * @return The bytes for filename. - */ - public com.google.protobuf.ByteString - getFilenameBytes() { - java.lang.Object ref = filename_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - filename_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * An optional name for the file (e.g., "document.pdf").
-     * 
- * - * string filename = 6; - * @param value The filename to set. - * @return This builder for chaining. - */ - public Builder setFilename( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - filename_ = value; - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * An optional name for the file (e.g., "document.pdf").
-     * 
- * - * string filename = 6; - * @return This builder for chaining. - */ - public Builder clearFilename() { - filename_ = getDefaultInstance().getFilename(); - bitField0_ = (bitField0_ & ~0x00000020); - onChanged(); - return this; - } - /** - *
-     * An optional name for the file (e.g., "document.pdf").
-     * 
- * - * string filename = 6; - * @param value The bytes for filename to set. - * @return This builder for chaining. - */ - public Builder setFilenameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - filename_ = value; - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - - private java.lang.Object mediaType_ = ""; - /** - *
-     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-     * This field is available for all part types.
-     * 
- * - * string media_type = 7; - * @return The mediaType. - */ - public java.lang.String getMediaType() { - java.lang.Object ref = mediaType_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - mediaType_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-     * This field is available for all part types.
-     * 
- * - * string media_type = 7; - * @return The bytes for mediaType. - */ - public com.google.protobuf.ByteString - getMediaTypeBytes() { - java.lang.Object ref = mediaType_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - mediaType_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-     * This field is available for all part types.
-     * 
- * - * string media_type = 7; - * @param value The mediaType to set. - * @return This builder for chaining. - */ - public Builder setMediaType( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - mediaType_ = value; - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - /** - *
-     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-     * This field is available for all part types.
-     * 
- * - * string media_type = 7; - * @return This builder for chaining. - */ - public Builder clearMediaType() { - mediaType_ = getDefaultInstance().getMediaType(); - bitField0_ = (bitField0_ & ~0x00000040); - onChanged(); - return this; - } - /** - *
-     * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-     * This field is available for all part types.
-     * 
- * - * string media_type = 7; - * @param value The bytes for mediaType to set. - * @return This builder for chaining. - */ - public Builder setMediaTypeBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - mediaType_ = value; - bitField0_ |= 0x00000040; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.Part) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.Part) - private static final io.a2a.grpc.Part DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.Part(); - } - - public static io.a2a.grpc.Part getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public Part parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.Part getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java deleted file mode 100644 index 0216594f2..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/PartOrBuilder.java +++ /dev/null @@ -1,187 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface PartOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Part) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The string content of the text part.
-   * 
- * - * string text = 1; - * @return Whether the text field is set. - */ - boolean hasText(); - /** - *
-   * The string content of the text part.
-   * 
- * - * string text = 1; - * @return The text. - */ - java.lang.String getText(); - /** - *
-   * The string content of the text part.
-   * 
- * - * string text = 1; - * @return The bytes for text. - */ - com.google.protobuf.ByteString - getTextBytes(); - - /** - *
-   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-   * 
- * - * bytes raw = 2; - * @return Whether the raw field is set. - */ - boolean hasRaw(); - /** - *
-   * The raw byte content of a file. In JSON serialization, this is encoded as a base64 string.
-   * 
- * - * bytes raw = 2; - * @return The raw. - */ - com.google.protobuf.ByteString getRaw(); - - /** - *
-   * A URL pointing to the file's content.
-   * 
- * - * string url = 3; - * @return Whether the url field is set. - */ - boolean hasUrl(); - /** - *
-   * A URL pointing to the file's content.
-   * 
- * - * string url = 3; - * @return The url. - */ - java.lang.String getUrl(); - /** - *
-   * A URL pointing to the file's content.
-   * 
- * - * string url = 3; - * @return The bytes for url. - */ - com.google.protobuf.ByteString - getUrlBytes(); - - /** - *
-   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-   * 
- * - * .google.protobuf.Value data = 4; - * @return Whether the data field is set. - */ - boolean hasData(); - /** - *
-   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-   * 
- * - * .google.protobuf.Value data = 4; - * @return The data. - */ - com.google.protobuf.Value getData(); - /** - *
-   * Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null).
-   * 
- * - * .google.protobuf.Value data = 4; - */ - com.google.protobuf.ValueOrBuilder getDataOrBuilder(); - - /** - *
-   * Optional metadata associated with this part.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return Whether the metadata field is set. - */ - boolean hasMetadata(); - /** - *
-   * Optional metadata associated with this part.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return The metadata. - */ - com.google.protobuf.Struct getMetadata(); - /** - *
-   * Optional metadata associated with this part.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - */ - com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); - - /** - *
-   * An optional name for the file (e.g., "document.pdf").
-   * 
- * - * string filename = 6; - * @return The filename. - */ - java.lang.String getFilename(); - /** - *
-   * An optional name for the file (e.g., "document.pdf").
-   * 
- * - * string filename = 6; - * @return The bytes for filename. - */ - com.google.protobuf.ByteString - getFilenameBytes(); - - /** - *
-   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-   * This field is available for all part types.
-   * 
- * - * string media_type = 7; - * @return The mediaType. - */ - java.lang.String getMediaType(); - /** - *
-   * The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png").
-   * This field is available for all part types.
-   * 
- * - * string media_type = 7; - * @return The bytes for mediaType. - */ - com.google.protobuf.ByteString - getMediaTypeBytes(); - - io.a2a.grpc.Part.ContentCase getContentCase(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java deleted file mode 100644 index 50f6032bb..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlow.java +++ /dev/null @@ -1,1050 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * DEPRECATED
- * 
- * - * Protobuf type {@code a2a.v1.PasswordOAuthFlow} - */ -@com.google.protobuf.Generated -public final class PasswordOAuthFlow extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.PasswordOAuthFlow) - PasswordOAuthFlowOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "PasswordOAuthFlow"); - } - // Use PasswordOAuthFlow.newBuilder() to construct. - private PasswordOAuthFlow(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private PasswordOAuthFlow() { - tokenUrl_ = ""; - refreshUrl_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); - } - - public static final int TOKEN_URL_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object tokenUrl_ = ""; - /** - *
-   * The token URL to be used for this flow. This MUST be in the form of a URL.
-   * The OAuth2 standard requires the use of TLS.
-   * 
- * - * string token_url = 1; - * @return The tokenUrl. - */ - @java.lang.Override - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } - } - /** - *
-   * The token URL to be used for this flow. This MUST be in the form of a URL.
-   * The OAuth2 standard requires the use of TLS.
-   * 
- * - * string token_url = 1; - * @return The bytes for tokenUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int REFRESH_URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object refreshUrl_ = ""; - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - @java.lang.Override - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } - } - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int SCOPES_FIELD_NUMBER = 3; - private static final class ScopesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_ScopesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, refreshUrl_); - } - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetScopes(), - ScopesDefaultEntryHolder.defaultEntry, - 3); - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tokenUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, tokenUrl_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(refreshUrl_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, refreshUrl_); - } - for (java.util.Map.Entry entry - : internalGetScopes().getMap().entrySet()) { - com.google.protobuf.MapEntry - scopes__ = ScopesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, scopes__); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.PasswordOAuthFlow)) { - return super.equals(obj); - } - io.a2a.grpc.PasswordOAuthFlow other = (io.a2a.grpc.PasswordOAuthFlow) obj; - - if (!getTokenUrl() - .equals(other.getTokenUrl())) return false; - if (!getRefreshUrl() - .equals(other.getRefreshUrl())) return false; - if (!internalGetScopes().equals( - other.internalGetScopes())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TOKEN_URL_FIELD_NUMBER; - hash = (53 * hash) + getTokenUrl().hashCode(); - hash = (37 * hash) + REFRESH_URL_FIELD_NUMBER; - hash = (53 * hash) + getRefreshUrl().hashCode(); - if (!internalGetScopes().getMap().isEmpty()) { - hash = (37 * hash) + SCOPES_FIELD_NUMBER; - hash = (53 * hash) + internalGetScopes().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.PasswordOAuthFlow parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.PasswordOAuthFlow parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.PasswordOAuthFlow prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * DEPRECATED
-   * 
- * - * Protobuf type {@code a2a.v1.PasswordOAuthFlow} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.PasswordOAuthFlow) - io.a2a.grpc.PasswordOAuthFlowOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 3: - return internalGetMutableScopes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.PasswordOAuthFlow.class, io.a2a.grpc.PasswordOAuthFlow.Builder.class); - } - - // Construct using io.a2a.grpc.PasswordOAuthFlow.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tokenUrl_ = ""; - refreshUrl_ = ""; - internalGetMutableScopes().clear(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PasswordOAuthFlow_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() { - return io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow build() { - io.a2a.grpc.PasswordOAuthFlow result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow buildPartial() { - io.a2a.grpc.PasswordOAuthFlow result = new io.a2a.grpc.PasswordOAuthFlow(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.PasswordOAuthFlow result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tokenUrl_ = tokenUrl_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.refreshUrl_ = refreshUrl_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.scopes_ = internalGetScopes(); - result.scopes_.makeImmutable(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.PasswordOAuthFlow) { - return mergeFrom((io.a2a.grpc.PasswordOAuthFlow)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.PasswordOAuthFlow other) { - if (other == io.a2a.grpc.PasswordOAuthFlow.getDefaultInstance()) return this; - if (!other.getTokenUrl().isEmpty()) { - tokenUrl_ = other.tokenUrl_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getRefreshUrl().isEmpty()) { - refreshUrl_ = other.refreshUrl_; - bitField0_ |= 0x00000002; - onChanged(); - } - internalGetMutableScopes().mergeFrom( - other.internalGetScopes()); - bitField0_ |= 0x00000004; - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - tokenUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - refreshUrl_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - com.google.protobuf.MapEntry - scopes__ = input.readMessage( - ScopesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableScopes().getMutableMap().put( - scopes__.getKey(), scopes__.getValue()); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tokenUrl_ = ""; - /** - *
-     * The token URL to be used for this flow. This MUST be in the form of a URL.
-     * The OAuth2 standard requires the use of TLS.
-     * 
- * - * string token_url = 1; - * @return The tokenUrl. - */ - public java.lang.String getTokenUrl() { - java.lang.Object ref = tokenUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tokenUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The token URL to be used for this flow. This MUST be in the form of a URL.
-     * The OAuth2 standard requires the use of TLS.
-     * 
- * - * string token_url = 1; - * @return The bytes for tokenUrl. - */ - public com.google.protobuf.ByteString - getTokenUrlBytes() { - java.lang.Object ref = tokenUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tokenUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The token URL to be used for this flow. This MUST be in the form of a URL.
-     * The OAuth2 standard requires the use of TLS.
-     * 
- * - * string token_url = 1; - * @param value The tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tokenUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow. This MUST be in the form of a URL.
-     * The OAuth2 standard requires the use of TLS.
-     * 
- * - * string token_url = 1; - * @return This builder for chaining. - */ - public Builder clearTokenUrl() { - tokenUrl_ = getDefaultInstance().getTokenUrl(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The token URL to be used for this flow. This MUST be in the form of a URL.
-     * The OAuth2 standard requires the use of TLS.
-     * 
- * - * string token_url = 1; - * @param value The bytes for tokenUrl to set. - * @return This builder for chaining. - */ - public Builder setTokenUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tokenUrl_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object refreshUrl_ = ""; - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - public java.lang.String getRefreshUrl() { - java.lang.Object ref = refreshUrl_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - refreshUrl_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - public com.google.protobuf.ByteString - getRefreshUrlBytes() { - java.lang.Object ref = refreshUrl_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - refreshUrl_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @param value The refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @return This builder for chaining. - */ - public Builder clearRefreshUrl() { - refreshUrl_ = getDefaultInstance().getRefreshUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The URL to be used for obtaining refresh tokens. This MUST be in the
-     * form of a URL. The OAuth2 standard requires the use of TLS.
-     * 
- * - * string refresh_url = 2; - * @param value The bytes for refreshUrl to set. - * @return This builder for chaining. - */ - public Builder setRefreshUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - refreshUrl_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> scopes_; - private com.google.protobuf.MapField - internalGetScopes() { - if (scopes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - return scopes_; - } - private com.google.protobuf.MapField - internalGetMutableScopes() { - if (scopes_ == null) { - scopes_ = com.google.protobuf.MapField.newMapField( - ScopesDefaultEntryHolder.defaultEntry); - } - if (!scopes_.isMutable()) { - scopes_ = scopes_.copy(); - } - bitField0_ |= 0x00000004; - onChanged(); - return scopes_; - } - public int getScopesCount() { - return internalGetScopes().getMap().size(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public boolean containsScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetScopes().getMap().containsKey(key); - } - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getScopes() { - return getScopesMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.util.Map getScopesMap() { - return internalGetScopes().getMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - @java.lang.Override - public java.lang.String getScopesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetScopes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - public Builder clearScopes() { - bitField0_ = (bitField0_ & ~0x00000004); - internalGetMutableScopes().getMutableMap() - .clear(); - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - public Builder removeScopes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableScopes().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableScopes() { - bitField0_ |= 0x00000004; - return internalGetMutableScopes().getMutableMap(); - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - public Builder putScopes( - java.lang.String key, - java.lang.String value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableScopes().getMutableMap() - .put(key, value); - bitField0_ |= 0x00000004; - return this; - } - /** - *
-     * The available scopes for the OAuth2 security scheme. A map between the
-     * scope name and a short description for it. The map MAY be empty.
-     * 
- * - * map<string, string> scopes = 3; - */ - public Builder putAllScopes( - java.util.Map values) { - internalGetMutableScopes().getMutableMap() - .putAll(values); - bitField0_ |= 0x00000004; - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.PasswordOAuthFlow) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.PasswordOAuthFlow) - private static final io.a2a.grpc.PasswordOAuthFlow DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.PasswordOAuthFlow(); - } - - public static io.a2a.grpc.PasswordOAuthFlow getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public PasswordOAuthFlow parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.PasswordOAuthFlow getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java deleted file mode 100644 index d319dd1e7..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/PasswordOAuthFlowOrBuilder.java +++ /dev/null @@ -1,115 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface PasswordOAuthFlowOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.PasswordOAuthFlow) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The token URL to be used for this flow. This MUST be in the form of a URL.
-   * The OAuth2 standard requires the use of TLS.
-   * 
- * - * string token_url = 1; - * @return The tokenUrl. - */ - java.lang.String getTokenUrl(); - /** - *
-   * The token URL to be used for this flow. This MUST be in the form of a URL.
-   * The OAuth2 standard requires the use of TLS.
-   * 
- * - * string token_url = 1; - * @return The bytes for tokenUrl. - */ - com.google.protobuf.ByteString - getTokenUrlBytes(); - - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The refreshUrl. - */ - java.lang.String getRefreshUrl(); - /** - *
-   * The URL to be used for obtaining refresh tokens. This MUST be in the
-   * form of a URL. The OAuth2 standard requires the use of TLS.
-   * 
- * - * string refresh_url = 2; - * @return The bytes for refreshUrl. - */ - com.google.protobuf.ByteString - getRefreshUrlBytes(); - - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - int getScopesCount(); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - boolean containsScopes( - java.lang.String key); - /** - * Use {@link #getScopesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getScopes(); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - java.util.Map - getScopesMap(); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - /* nullable */ -java.lang.String getScopesOrDefault( - java.lang.String key, - /* nullable */ -java.lang.String defaultValue); - /** - *
-   * The available scopes for the OAuth2 security scheme. A map between the
-   * scope name and a short description for it. The map MAY be empty.
-   * 
- * - * map<string, string> scopes = 3; - */ - java.lang.String getScopesOrThrow( - java.lang.String key); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java deleted file mode 100644 index 5c23d23ba..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfig.java +++ /dev/null @@ -1,1109 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:PushNotificationConfig]
- * Configuration for setting up push notifications for task updates.
- * 
- * - * Protobuf type {@code a2a.v1.PushNotificationConfig} - */ -@com.google.protobuf.Generated -public final class PushNotificationConfig extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.PushNotificationConfig) - PushNotificationConfigOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "PushNotificationConfig"); - } - // Use PushNotificationConfig.newBuilder() to construct. - private PushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private PushNotificationConfig() { - id_ = ""; - url_ = ""; - token_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.PushNotificationConfig.class, io.a2a.grpc.PushNotificationConfig.Builder.class); - } - - private int bitField0_; - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * A unique identifier (e.g. UUID) for this push notification.
-   * 
- * - * string id = 1; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * A unique identifier (e.g. UUID) for this push notification.
-   * 
- * - * string id = 1; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int URL_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object url_ = ""; - /** - *
-   * Url to send the notification too
-   * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - @java.lang.Override - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } - } - /** - *
-   * Url to send the notification too
-   * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TOKEN_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object token_ = ""; - /** - *
-   * Token unique for this task/session
-   * 
- * - * string token = 3; - * @return The token. - */ - @java.lang.Override - public java.lang.String getToken() { - java.lang.Object ref = token_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - token_ = s; - return s; - } - } - /** - *
-   * Token unique for this task/session
-   * 
- * - * string token = 3; - * @return The bytes for token. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTokenBytes() { - java.lang.Object ref = token_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - token_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int AUTHENTICATION_FIELD_NUMBER = 4; - private io.a2a.grpc.AuthenticationInfo authentication_; - /** - *
-   * Authentication information required to send the notification
-   * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - * @return Whether the authentication field is set. - */ - @java.lang.Override - public boolean hasAuthentication() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * Authentication information required to send the notification
-   * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - * @return The authentication. - */ - @java.lang.Override - public io.a2a.grpc.AuthenticationInfo getAuthentication() { - return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } - /** - *
-   * Authentication information required to send the notification
-   * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - @java.lang.Override - public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { - return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, token_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(4, getAuthentication()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(url_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, url_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(token_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, token_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, getAuthentication()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.PushNotificationConfig)) { - return super.equals(obj); - } - io.a2a.grpc.PushNotificationConfig other = (io.a2a.grpc.PushNotificationConfig) obj; - - if (!getId() - .equals(other.getId())) return false; - if (!getUrl() - .equals(other.getUrl())) return false; - if (!getToken() - .equals(other.getToken())) return false; - if (hasAuthentication() != other.hasAuthentication()) return false; - if (hasAuthentication()) { - if (!getAuthentication() - .equals(other.getAuthentication())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (37 * hash) + URL_FIELD_NUMBER; - hash = (53 * hash) + getUrl().hashCode(); - hash = (37 * hash) + TOKEN_FIELD_NUMBER; - hash = (53 * hash) + getToken().hashCode(); - if (hasAuthentication()) { - hash = (37 * hash) + AUTHENTICATION_FIELD_NUMBER; - hash = (53 * hash) + getAuthentication().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.PushNotificationConfig parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.PushNotificationConfig parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.PushNotificationConfig parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.PushNotificationConfig parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.PushNotificationConfig prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:PushNotificationConfig]
-   * Configuration for setting up push notifications for task updates.
-   * 
- * - * Protobuf type {@code a2a.v1.PushNotificationConfig} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.PushNotificationConfig) - io.a2a.grpc.PushNotificationConfigOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.PushNotificationConfig.class, io.a2a.grpc.PushNotificationConfig.Builder.class); - } - - // Construct using io.a2a.grpc.PushNotificationConfig.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetAuthenticationFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - id_ = ""; - url_ = ""; - token_ = ""; - authentication_ = null; - if (authenticationBuilder_ != null) { - authenticationBuilder_.dispose(); - authenticationBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_PushNotificationConfig_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getDefaultInstanceForType() { - return io.a2a.grpc.PushNotificationConfig.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig build() { - io.a2a.grpc.PushNotificationConfig result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig buildPartial() { - io.a2a.grpc.PushNotificationConfig result = new io.a2a.grpc.PushNotificationConfig(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.PushNotificationConfig result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.id_ = id_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.url_ = url_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.token_ = token_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { - result.authentication_ = authenticationBuilder_ == null - ? authentication_ - : authenticationBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.PushNotificationConfig) { - return mergeFrom((io.a2a.grpc.PushNotificationConfig)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.PushNotificationConfig other) { - if (other == io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) return this; - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getUrl().isEmpty()) { - url_ = other.url_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getToken().isEmpty()) { - token_ = other.token_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (other.hasAuthentication()) { - mergeAuthentication(other.getAuthentication()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - url_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - token_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - input.readMessage( - internalGetAuthenticationFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object id_ = ""; - /** - *
-     * A unique identifier (e.g. UUID) for this push notification.
-     * 
- * - * string id = 1; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * A unique identifier (e.g. UUID) for this push notification.
-     * 
- * - * string id = 1; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * A unique identifier (e.g. UUID) for this push notification.
-     * 
- * - * string id = 1; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * A unique identifier (e.g. UUID) for this push notification.
-     * 
- * - * string id = 1; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * A unique identifier (e.g. UUID) for this push notification.
-     * 
- * - * string id = 1; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object url_ = ""; - /** - *
-     * Url to send the notification too
-     * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - public java.lang.String getUrl() { - java.lang.Object ref = url_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - url_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Url to send the notification too
-     * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - public com.google.protobuf.ByteString - getUrlBytes() { - java.lang.Object ref = url_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - url_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Url to send the notification too
-     * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The url to set. - * @return This builder for chaining. - */ - public Builder setUrl( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - url_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Url to send the notification too
-     * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearUrl() { - url_ = getDefaultInstance().getUrl(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * Url to send the notification too
-     * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for url to set. - * @return This builder for chaining. - */ - public Builder setUrlBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - url_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object token_ = ""; - /** - *
-     * Token unique for this task/session
-     * 
- * - * string token = 3; - * @return The token. - */ - public java.lang.String getToken() { - java.lang.Object ref = token_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - token_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Token unique for this task/session
-     * 
- * - * string token = 3; - * @return The bytes for token. - */ - public com.google.protobuf.ByteString - getTokenBytes() { - java.lang.Object ref = token_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - token_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Token unique for this task/session
-     * 
- * - * string token = 3; - * @param value The token to set. - * @return This builder for chaining. - */ - public Builder setToken( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - token_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * Token unique for this task/session
-     * 
- * - * string token = 3; - * @return This builder for chaining. - */ - public Builder clearToken() { - token_ = getDefaultInstance().getToken(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * Token unique for this task/session
-     * 
- * - * string token = 3; - * @param value The bytes for token to set. - * @return This builder for chaining. - */ - public Builder setTokenBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - token_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private io.a2a.grpc.AuthenticationInfo authentication_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> authenticationBuilder_; - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - * @return Whether the authentication field is set. - */ - public boolean hasAuthentication() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - * @return The authentication. - */ - public io.a2a.grpc.AuthenticationInfo getAuthentication() { - if (authenticationBuilder_ == null) { - return authentication_ == null ? io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } else { - return authenticationBuilder_.getMessage(); - } - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder setAuthentication(io.a2a.grpc.AuthenticationInfo value) { - if (authenticationBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - authentication_ = value; - } else { - authenticationBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder setAuthentication( - io.a2a.grpc.AuthenticationInfo.Builder builderForValue) { - if (authenticationBuilder_ == null) { - authentication_ = builderForValue.build(); - } else { - authenticationBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder mergeAuthentication(io.a2a.grpc.AuthenticationInfo value) { - if (authenticationBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - authentication_ != null && - authentication_ != io.a2a.grpc.AuthenticationInfo.getDefaultInstance()) { - getAuthenticationBuilder().mergeFrom(value); - } else { - authentication_ = value; - } - } else { - authenticationBuilder_.mergeFrom(value); - } - if (authentication_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - public Builder clearAuthentication() { - bitField0_ = (bitField0_ & ~0x00000008); - authentication_ = null; - if (authenticationBuilder_ != null) { - authenticationBuilder_.dispose(); - authenticationBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - public io.a2a.grpc.AuthenticationInfo.Builder getAuthenticationBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetAuthenticationFieldBuilder().getBuilder(); - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - public io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder() { - if (authenticationBuilder_ != null) { - return authenticationBuilder_.getMessageOrBuilder(); - } else { - return authentication_ == null ? - io.a2a.grpc.AuthenticationInfo.getDefaultInstance() : authentication_; - } - } - /** - *
-     * Authentication information required to send the notification
-     * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder> - internalGetAuthenticationFieldBuilder() { - if (authenticationBuilder_ == null) { - authenticationBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.AuthenticationInfo, io.a2a.grpc.AuthenticationInfo.Builder, io.a2a.grpc.AuthenticationInfoOrBuilder>( - getAuthentication(), - getParentForChildren(), - isClean()); - authentication_ = null; - } - return authenticationBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.PushNotificationConfig) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.PushNotificationConfig) - private static final io.a2a.grpc.PushNotificationConfig DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.PushNotificationConfig(); - } - - public static io.a2a.grpc.PushNotificationConfig getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public PushNotificationConfig parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java deleted file mode 100644 index b65c0d5a0..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/PushNotificationConfigOrBuilder.java +++ /dev/null @@ -1,99 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface PushNotificationConfigOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.PushNotificationConfig) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * A unique identifier (e.g. UUID) for this push notification.
-   * 
- * - * string id = 1; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * A unique identifier (e.g. UUID) for this push notification.
-   * 
- * - * string id = 1; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - *
-   * Url to send the notification too
-   * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The url. - */ - java.lang.String getUrl(); - /** - *
-   * Url to send the notification too
-   * 
- * - * string url = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for url. - */ - com.google.protobuf.ByteString - getUrlBytes(); - - /** - *
-   * Token unique for this task/session
-   * 
- * - * string token = 3; - * @return The token. - */ - java.lang.String getToken(); - /** - *
-   * Token unique for this task/session
-   * 
- * - * string token = 3; - * @return The bytes for token. - */ - com.google.protobuf.ByteString - getTokenBytes(); - - /** - *
-   * Authentication information required to send the notification
-   * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - * @return Whether the authentication field is set. - */ - boolean hasAuthentication(); - /** - *
-   * Authentication information required to send the notification
-   * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - * @return The authentication. - */ - io.a2a.grpc.AuthenticationInfo getAuthentication(); - /** - *
-   * Authentication information required to send the notification
-   * 
- * - * .a2a.v1.AuthenticationInfo authentication = 4; - */ - io.a2a.grpc.AuthenticationInfoOrBuilder getAuthenticationOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Role.java b/spec-grpc/src/main/java/io/a2a/grpc/Role.java deleted file mode 100644 index 1d8b02c6e..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/Role.java +++ /dev/null @@ -1,155 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:Role]
- * Defines the sender of a message in A2A protocol communication.
- * 
- * - * Protobuf enum {@code a2a.v1.Role} - */ -@com.google.protobuf.Generated -public enum Role - implements com.google.protobuf.ProtocolMessageEnum { - /** - * ROLE_UNSPECIFIED = 0; - */ - ROLE_UNSPECIFIED(0), - /** - *
-   * USER role refers to communication from the client to the server.
-   * 
- * - * ROLE_USER = 1; - */ - ROLE_USER(1), - /** - *
-   * AGENT role refers to communication from the server to the client.
-   * 
- * - * ROLE_AGENT = 2; - */ - ROLE_AGENT(2), - UNRECOGNIZED(-1), - ; - - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "Role"); - } - /** - * ROLE_UNSPECIFIED = 0; - */ - public static final int ROLE_UNSPECIFIED_VALUE = 0; - /** - *
-   * USER role refers to communication from the client to the server.
-   * 
- * - * ROLE_USER = 1; - */ - public static final int ROLE_USER_VALUE = 1; - /** - *
-   * AGENT role refers to communication from the server to the client.
-   * 
- * - * ROLE_AGENT = 2; - */ - public static final int ROLE_AGENT_VALUE = 2; - - - public final int getNumber() { - if (this == UNRECOGNIZED) { - throw new java.lang.IllegalArgumentException( - "Can't get the number of an unknown enum value."); - } - return value; - } - - /** - * @param value The numeric wire value of the corresponding enum entry. - * @return The enum associated with the given numeric wire value. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static Role valueOf(int value) { - return forNumber(value); - } - - /** - * @param value The numeric wire value of the corresponding enum entry. - * @return The enum associated with the given numeric wire value. - */ - public static Role forNumber(int value) { - switch (value) { - case 0: return ROLE_UNSPECIFIED; - case 1: return ROLE_USER; - case 2: return ROLE_AGENT; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static final com.google.protobuf.Internal.EnumLiteMap< - Role> internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public Role findValueByNumber(int number) { - return Role.forNumber(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - if (this == UNRECOGNIZED) { - throw new java.lang.IllegalStateException( - "Can't get the descriptor of an unrecognized enum value."); - } - return getDescriptor().getValues().get(ordinal()); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return io.a2a.grpc.A2A.getDescriptor().getEnumTypes().get(1); - } - - private static final Role[] VALUES = values(); - - public static Role valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - if (desc.getIndex() == -1) { - return UNRECOGNIZED; - } - return VALUES[desc.getIndex()]; - } - - private final int value; - - private Role(int value) { - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:a2a.v1.Role) -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java deleted file mode 100644 index 945b2608d..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirement.java +++ /dev/null @@ -1,672 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - * Protobuf type {@code a2a.v1.SecurityRequirement} - */ -@com.google.protobuf.Generated -public final class SecurityRequirement extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SecurityRequirement) - SecurityRequirementOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "SecurityRequirement"); - } - // Use SecurityRequirement.newBuilder() to construct. - private SecurityRequirement(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private SecurityRequirement() { - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 1: - return internalGetSchemes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class); - } - - public static final int SCHEMES_FIELD_NUMBER = 1; - private static final class SchemesDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, io.a2a.grpc.StringList> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_SchemesEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.MESSAGE, - io.a2a.grpc.StringList.getDefaultInstance()); - } - @SuppressWarnings("serial") - private com.google.protobuf.MapField< - java.lang.String, io.a2a.grpc.StringList> schemes_; - private com.google.protobuf.MapField - internalGetSchemes() { - if (schemes_ == null) { - return com.google.protobuf.MapField.emptyMapField( - SchemesDefaultEntryHolder.defaultEntry); - } - return schemes_; - } - public int getSchemesCount() { - return internalGetSchemes().getMap().size(); - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public boolean containsSchemes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetSchemes().getMap().containsKey(key); - } - /** - * Use {@link #getSchemesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getSchemes() { - return getSchemesMap(); - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public java.util.Map getSchemesMap() { - return internalGetSchemes().getMap(); - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public /* nullable */ -io.a2a.grpc.StringList getSchemesOrDefault( - java.lang.String key, - /* nullable */ -io.a2a.grpc.StringList defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetSchemes().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public io.a2a.grpc.StringList getSchemesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = - internalGetSchemes().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - com.google.protobuf.GeneratedMessage - .serializeStringMapTo( - output, - internalGetSchemes(), - SchemesDefaultEntryHolder.defaultEntry, - 1); - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - for (java.util.Map.Entry entry - : internalGetSchemes().getMap().entrySet()) { - com.google.protobuf.MapEntry - schemes__ = SchemesDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, schemes__); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.SecurityRequirement)) { - return super.equals(obj); - } - io.a2a.grpc.SecurityRequirement other = (io.a2a.grpc.SecurityRequirement) obj; - - if (!internalGetSchemes().equals( - other.internalGetSchemes())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (!internalGetSchemes().getMap().isEmpty()) { - hash = (37 * hash) + SCHEMES_FIELD_NUMBER; - hash = (53 * hash) + internalGetSchemes().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.SecurityRequirement parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SecurityRequirement parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SecurityRequirement parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SecurityRequirement parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SecurityRequirement parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SecurityRequirement parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SecurityRequirement parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SecurityRequirement parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.SecurityRequirement parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.SecurityRequirement parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.SecurityRequirement parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SecurityRequirement parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.SecurityRequirement prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code a2a.v1.SecurityRequirement} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SecurityRequirement) - io.a2a.grpc.SecurityRequirementOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMapFieldReflection( - int number) { - switch (number) { - case 1: - return internalGetSchemes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapFieldReflectionAccessor internalGetMutableMapFieldReflection( - int number) { - switch (number) { - case 1: - return internalGetMutableSchemes(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SecurityRequirement.class, io.a2a.grpc.SecurityRequirement.Builder.class); - } - - // Construct using io.a2a.grpc.SecurityRequirement.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - internalGetMutableSchemes().clear(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityRequirement_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.SecurityRequirement getDefaultInstanceForType() { - return io.a2a.grpc.SecurityRequirement.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.SecurityRequirement build() { - io.a2a.grpc.SecurityRequirement result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.SecurityRequirement buildPartial() { - io.a2a.grpc.SecurityRequirement result = new io.a2a.grpc.SecurityRequirement(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.SecurityRequirement result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.schemes_ = internalGetSchemes().build(SchemesDefaultEntryHolder.defaultEntry); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.SecurityRequirement) { - return mergeFrom((io.a2a.grpc.SecurityRequirement)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.SecurityRequirement other) { - if (other == io.a2a.grpc.SecurityRequirement.getDefaultInstance()) return this; - internalGetMutableSchemes().mergeFrom( - other.internalGetSchemes()); - bitField0_ |= 0x00000001; - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - com.google.protobuf.MapEntry - schemes__ = input.readMessage( - SchemesDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - internalGetMutableSchemes().ensureBuilderMap().put( - schemes__.getKey(), schemes__.getValue()); - bitField0_ |= 0x00000001; - break; - } // case 10 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private static final class SchemesConverter implements com.google.protobuf.MapFieldBuilder.Converter { - @java.lang.Override - public io.a2a.grpc.StringList build(io.a2a.grpc.StringListOrBuilder val) { - if (val instanceof io.a2a.grpc.StringList) { return (io.a2a.grpc.StringList) val; } - return ((io.a2a.grpc.StringList.Builder) val).build(); - } - - @java.lang.Override - public com.google.protobuf.MapEntry defaultEntry() { - return SchemesDefaultEntryHolder.defaultEntry; - } - }; - private static final SchemesConverter schemesConverter = new SchemesConverter(); - - private com.google.protobuf.MapFieldBuilder< - java.lang.String, io.a2a.grpc.StringListOrBuilder, io.a2a.grpc.StringList, io.a2a.grpc.StringList.Builder> schemes_; - private com.google.protobuf.MapFieldBuilder - internalGetSchemes() { - if (schemes_ == null) { - return new com.google.protobuf.MapFieldBuilder<>(schemesConverter); - } - return schemes_; - } - private com.google.protobuf.MapFieldBuilder - internalGetMutableSchemes() { - if (schemes_ == null) { - schemes_ = new com.google.protobuf.MapFieldBuilder<>(schemesConverter); - } - bitField0_ |= 0x00000001; - onChanged(); - return schemes_; - } - public int getSchemesCount() { - return internalGetSchemes().ensureBuilderMap().size(); - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public boolean containsSchemes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - return internalGetSchemes().ensureBuilderMap().containsKey(key); - } - /** - * Use {@link #getSchemesMap()} instead. - */ - @java.lang.Override - @java.lang.Deprecated - public java.util.Map getSchemes() { - return getSchemesMap(); - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public java.util.Map getSchemesMap() { - return internalGetSchemes().getImmutableMap(); - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public /* nullable */ -io.a2a.grpc.StringList getSchemesOrDefault( - java.lang.String key, - /* nullable */ -io.a2a.grpc.StringList defaultValue) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = internalGetMutableSchemes().ensureBuilderMap(); - return map.containsKey(key) ? schemesConverter.build(map.get(key)) : defaultValue; - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - @java.lang.Override - public io.a2a.grpc.StringList getSchemesOrThrow( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - java.util.Map map = internalGetMutableSchemes().ensureBuilderMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return schemesConverter.build(map.get(key)); - } - public Builder clearSchemes() { - bitField0_ = (bitField0_ & ~0x00000001); - internalGetMutableSchemes().clear(); - return this; - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - public Builder removeSchemes( - java.lang.String key) { - if (key == null) { throw new NullPointerException("map key"); } - internalGetMutableSchemes().ensureBuilderMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableSchemes() { - bitField0_ |= 0x00000001; - return internalGetMutableSchemes().ensureMessageMap(); - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - public Builder putSchemes( - java.lang.String key, - io.a2a.grpc.StringList value) { - if (key == null) { throw new NullPointerException("map key"); } - if (value == null) { throw new NullPointerException("map value"); } - internalGetMutableSchemes().ensureBuilderMap() - .put(key, value); - bitField0_ |= 0x00000001; - return this; - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - public Builder putAllSchemes( - java.util.Map values) { - for (java.util.Map.Entry e : values.entrySet()) { - if (e.getKey() == null || e.getValue() == null) { - throw new NullPointerException(); - } - } - internalGetMutableSchemes().ensureBuilderMap() - .putAll(values); - bitField0_ |= 0x00000001; - return this; - } - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - public io.a2a.grpc.StringList.Builder putSchemesBuilderIfAbsent( - java.lang.String key) { - java.util.Map builderMap = internalGetMutableSchemes().ensureBuilderMap(); - io.a2a.grpc.StringListOrBuilder entry = builderMap.get(key); - if (entry == null) { - entry = io.a2a.grpc.StringList.newBuilder(); - builderMap.put(key, entry); - } - if (entry instanceof io.a2a.grpc.StringList) { - entry = ((io.a2a.grpc.StringList) entry).toBuilder(); - builderMap.put(key, entry); - } - return (io.a2a.grpc.StringList.Builder) entry; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.SecurityRequirement) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.SecurityRequirement) - private static final io.a2a.grpc.SecurityRequirement DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.SecurityRequirement(); - } - - public static io.a2a.grpc.SecurityRequirement getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public SecurityRequirement parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.SecurityRequirement getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java deleted file mode 100644 index 14b23d252..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityRequirementOrBuilder.java +++ /dev/null @@ -1,46 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface SecurityRequirementOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SecurityRequirement) - com.google.protobuf.MessageOrBuilder { - - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - int getSchemesCount(); - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - boolean containsSchemes( - java.lang.String key); - /** - * Use {@link #getSchemesMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getSchemes(); - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - java.util.Map - getSchemesMap(); - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - /* nullable */ -io.a2a.grpc.StringList getSchemesOrDefault( - java.lang.String key, - /* nullable */ -io.a2a.grpc.StringList defaultValue); - /** - * map<string, .a2a.v1.StringList> schemes = 1; - */ - io.a2a.grpc.StringList getSchemesOrThrow( - java.lang.String key); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java b/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java deleted file mode 100644 index c1202fccf..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecurityScheme.java +++ /dev/null @@ -1,1735 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:SecurityScheme]
- * Defines a security scheme that can be used to secure an agent's endpoints.
- * This is a discriminated union type based on the OpenAPI 3.2 Security Scheme Object.
- * See: https://spec.openapis.org/oas/v3.2.0.html#security-scheme-object
- * 
- * - * Protobuf type {@code a2a.v1.SecurityScheme} - */ -@com.google.protobuf.Generated -public final class SecurityScheme extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SecurityScheme) - SecuritySchemeOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "SecurityScheme"); - } - // Use SecurityScheme.newBuilder() to construct. - private SecurityScheme(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private SecurityScheme() { - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SecurityScheme.class, io.a2a.grpc.SecurityScheme.Builder.class); - } - - private int schemeCase_ = 0; - @SuppressWarnings("serial") - private java.lang.Object scheme_; - public enum SchemeCase - implements com.google.protobuf.Internal.EnumLite, - com.google.protobuf.AbstractMessage.InternalOneOfEnum { - API_KEY_SECURITY_SCHEME(1), - HTTP_AUTH_SECURITY_SCHEME(2), - OAUTH2_SECURITY_SCHEME(3), - OPEN_ID_CONNECT_SECURITY_SCHEME(4), - MTLS_SECURITY_SCHEME(5), - SCHEME_NOT_SET(0); - private final int value; - private SchemeCase(int value) { - this.value = value; - } - /** - * @param value The number of the enum to look for. - * @return The enum associated with the given number. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static SchemeCase valueOf(int value) { - return forNumber(value); - } - - public static SchemeCase forNumber(int value) { - switch (value) { - case 1: return API_KEY_SECURITY_SCHEME; - case 2: return HTTP_AUTH_SECURITY_SCHEME; - case 3: return OAUTH2_SECURITY_SCHEME; - case 4: return OPEN_ID_CONNECT_SECURITY_SCHEME; - case 5: return MTLS_SECURITY_SCHEME; - case 0: return SCHEME_NOT_SET; - default: return null; - } - } - public int getNumber() { - return this.value; - } - }; - - public SchemeCase - getSchemeCase() { - return SchemeCase.forNumber( - schemeCase_); - } - - public static final int API_KEY_SECURITY_SCHEME_FIELD_NUMBER = 1; - /** - *
-   * API key-based authentication.
-   * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - * @return Whether the apiKeySecurityScheme field is set. - */ - @java.lang.Override - public boolean hasApiKeySecurityScheme() { - return schemeCase_ == 1; - } - /** - *
-   * API key-based authentication.
-   * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - * @return The apiKeySecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() { - if (schemeCase_ == 1) { - return (io.a2a.grpc.APIKeySecurityScheme) scheme_; - } - return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance(); - } - /** - *
-   * API key-based authentication.
-   * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - @java.lang.Override - public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() { - if (schemeCase_ == 1) { - return (io.a2a.grpc.APIKeySecurityScheme) scheme_; - } - return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance(); - } - - public static final int HTTP_AUTH_SECURITY_SCHEME_FIELD_NUMBER = 2; - /** - *
-   * HTTP authentication (Basic, Bearer, etc.).
-   * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - * @return Whether the httpAuthSecurityScheme field is set. - */ - @java.lang.Override - public boolean hasHttpAuthSecurityScheme() { - return schemeCase_ == 2; - } - /** - *
-   * HTTP authentication (Basic, Bearer, etc.).
-   * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - * @return The httpAuthSecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() { - if (schemeCase_ == 2) { - return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_; - } - return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); - } - /** - *
-   * HTTP authentication (Basic, Bearer, etc.).
-   * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() { - if (schemeCase_ == 2) { - return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_; - } - return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); - } - - public static final int OAUTH2_SECURITY_SCHEME_FIELD_NUMBER = 3; - /** - *
-   * OAuth 2.0 authentication.
-   * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - * @return Whether the oauth2SecurityScheme field is set. - */ - @java.lang.Override - public boolean hasOauth2SecurityScheme() { - return schemeCase_ == 3; - } - /** - *
-   * OAuth 2.0 authentication.
-   * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - * @return The oauth2SecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() { - if (schemeCase_ == 3) { - return (io.a2a.grpc.OAuth2SecurityScheme) scheme_; - } - return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance(); - } - /** - *
-   * OAuth 2.0 authentication.
-   * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - @java.lang.Override - public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() { - if (schemeCase_ == 3) { - return (io.a2a.grpc.OAuth2SecurityScheme) scheme_; - } - return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance(); - } - - public static final int OPEN_ID_CONNECT_SECURITY_SCHEME_FIELD_NUMBER = 4; - /** - *
-   * OpenID Connect authentication.
-   * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - * @return Whether the openIdConnectSecurityScheme field is set. - */ - @java.lang.Override - public boolean hasOpenIdConnectSecurityScheme() { - return schemeCase_ == 4; - } - /** - *
-   * OpenID Connect authentication.
-   * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - * @return The openIdConnectSecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() { - if (schemeCase_ == 4) { - return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_; - } - return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); - } - /** - *
-   * OpenID Connect authentication.
-   * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() { - if (schemeCase_ == 4) { - return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_; - } - return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); - } - - public static final int MTLS_SECURITY_SCHEME_FIELD_NUMBER = 5; - /** - *
-   * Mutual TLS authentication.
-   * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - * @return Whether the mtlsSecurityScheme field is set. - */ - @java.lang.Override - public boolean hasMtlsSecurityScheme() { - return schemeCase_ == 5; - } - /** - *
-   * Mutual TLS authentication.
-   * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - * @return The mtlsSecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() { - if (schemeCase_ == 5) { - return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_; - } - return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance(); - } - /** - *
-   * Mutual TLS authentication.
-   * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - @java.lang.Override - public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() { - if (schemeCase_ == 5) { - return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_; - } - return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance(); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (schemeCase_ == 1) { - output.writeMessage(1, (io.a2a.grpc.APIKeySecurityScheme) scheme_); - } - if (schemeCase_ == 2) { - output.writeMessage(2, (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_); - } - if (schemeCase_ == 3) { - output.writeMessage(3, (io.a2a.grpc.OAuth2SecurityScheme) scheme_); - } - if (schemeCase_ == 4) { - output.writeMessage(4, (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_); - } - if (schemeCase_ == 5) { - output.writeMessage(5, (io.a2a.grpc.MutualTlsSecurityScheme) scheme_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (schemeCase_ == 1) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, (io.a2a.grpc.APIKeySecurityScheme) scheme_); - } - if (schemeCase_ == 2) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_); - } - if (schemeCase_ == 3) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, (io.a2a.grpc.OAuth2SecurityScheme) scheme_); - } - if (schemeCase_ == 4) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_); - } - if (schemeCase_ == 5) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, (io.a2a.grpc.MutualTlsSecurityScheme) scheme_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.SecurityScheme)) { - return super.equals(obj); - } - io.a2a.grpc.SecurityScheme other = (io.a2a.grpc.SecurityScheme) obj; - - if (!getSchemeCase().equals(other.getSchemeCase())) return false; - switch (schemeCase_) { - case 1: - if (!getApiKeySecurityScheme() - .equals(other.getApiKeySecurityScheme())) return false; - break; - case 2: - if (!getHttpAuthSecurityScheme() - .equals(other.getHttpAuthSecurityScheme())) return false; - break; - case 3: - if (!getOauth2SecurityScheme() - .equals(other.getOauth2SecurityScheme())) return false; - break; - case 4: - if (!getOpenIdConnectSecurityScheme() - .equals(other.getOpenIdConnectSecurityScheme())) return false; - break; - case 5: - if (!getMtlsSecurityScheme() - .equals(other.getMtlsSecurityScheme())) return false; - break; - case 0: - default: - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - switch (schemeCase_) { - case 1: - hash = (37 * hash) + API_KEY_SECURITY_SCHEME_FIELD_NUMBER; - hash = (53 * hash) + getApiKeySecurityScheme().hashCode(); - break; - case 2: - hash = (37 * hash) + HTTP_AUTH_SECURITY_SCHEME_FIELD_NUMBER; - hash = (53 * hash) + getHttpAuthSecurityScheme().hashCode(); - break; - case 3: - hash = (37 * hash) + OAUTH2_SECURITY_SCHEME_FIELD_NUMBER; - hash = (53 * hash) + getOauth2SecurityScheme().hashCode(); - break; - case 4: - hash = (37 * hash) + OPEN_ID_CONNECT_SECURITY_SCHEME_FIELD_NUMBER; - hash = (53 * hash) + getOpenIdConnectSecurityScheme().hashCode(); - break; - case 5: - hash = (37 * hash) + MTLS_SECURITY_SCHEME_FIELD_NUMBER; - hash = (53 * hash) + getMtlsSecurityScheme().hashCode(); - break; - case 0: - default: - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.SecurityScheme parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SecurityScheme parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SecurityScheme parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SecurityScheme parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SecurityScheme parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SecurityScheme parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SecurityScheme parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SecurityScheme parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.SecurityScheme parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.SecurityScheme parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.SecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SecurityScheme parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.SecurityScheme prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:SecurityScheme]
-   * Defines a security scheme that can be used to secure an agent's endpoints.
-   * This is a discriminated union type based on the OpenAPI 3.2 Security Scheme Object.
-   * See: https://spec.openapis.org/oas/v3.2.0.html#security-scheme-object
-   * 
- * - * Protobuf type {@code a2a.v1.SecurityScheme} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SecurityScheme) - io.a2a.grpc.SecuritySchemeOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SecurityScheme.class, io.a2a.grpc.SecurityScheme.Builder.class); - } - - // Construct using io.a2a.grpc.SecurityScheme.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - if (apiKeySecuritySchemeBuilder_ != null) { - apiKeySecuritySchemeBuilder_.clear(); - } - if (httpAuthSecuritySchemeBuilder_ != null) { - httpAuthSecuritySchemeBuilder_.clear(); - } - if (oauth2SecuritySchemeBuilder_ != null) { - oauth2SecuritySchemeBuilder_.clear(); - } - if (openIdConnectSecuritySchemeBuilder_ != null) { - openIdConnectSecuritySchemeBuilder_.clear(); - } - if (mtlsSecuritySchemeBuilder_ != null) { - mtlsSecuritySchemeBuilder_.clear(); - } - schemeCase_ = 0; - scheme_ = null; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SecurityScheme_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.SecurityScheme getDefaultInstanceForType() { - return io.a2a.grpc.SecurityScheme.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.SecurityScheme build() { - io.a2a.grpc.SecurityScheme result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.SecurityScheme buildPartial() { - io.a2a.grpc.SecurityScheme result = new io.a2a.grpc.SecurityScheme(this); - if (bitField0_ != 0) { buildPartial0(result); } - buildPartialOneofs(result); - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.SecurityScheme result) { - int from_bitField0_ = bitField0_; - } - - private void buildPartialOneofs(io.a2a.grpc.SecurityScheme result) { - result.schemeCase_ = schemeCase_; - result.scheme_ = this.scheme_; - if (schemeCase_ == 1 && - apiKeySecuritySchemeBuilder_ != null) { - result.scheme_ = apiKeySecuritySchemeBuilder_.build(); - } - if (schemeCase_ == 2 && - httpAuthSecuritySchemeBuilder_ != null) { - result.scheme_ = httpAuthSecuritySchemeBuilder_.build(); - } - if (schemeCase_ == 3 && - oauth2SecuritySchemeBuilder_ != null) { - result.scheme_ = oauth2SecuritySchemeBuilder_.build(); - } - if (schemeCase_ == 4 && - openIdConnectSecuritySchemeBuilder_ != null) { - result.scheme_ = openIdConnectSecuritySchemeBuilder_.build(); - } - if (schemeCase_ == 5 && - mtlsSecuritySchemeBuilder_ != null) { - result.scheme_ = mtlsSecuritySchemeBuilder_.build(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.SecurityScheme) { - return mergeFrom((io.a2a.grpc.SecurityScheme)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.SecurityScheme other) { - if (other == io.a2a.grpc.SecurityScheme.getDefaultInstance()) return this; - switch (other.getSchemeCase()) { - case API_KEY_SECURITY_SCHEME: { - mergeApiKeySecurityScheme(other.getApiKeySecurityScheme()); - break; - } - case HTTP_AUTH_SECURITY_SCHEME: { - mergeHttpAuthSecurityScheme(other.getHttpAuthSecurityScheme()); - break; - } - case OAUTH2_SECURITY_SCHEME: { - mergeOauth2SecurityScheme(other.getOauth2SecurityScheme()); - break; - } - case OPEN_ID_CONNECT_SECURITY_SCHEME: { - mergeOpenIdConnectSecurityScheme(other.getOpenIdConnectSecurityScheme()); - break; - } - case MTLS_SECURITY_SCHEME: { - mergeMtlsSecurityScheme(other.getMtlsSecurityScheme()); - break; - } - case SCHEME_NOT_SET: { - break; - } - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - input.readMessage( - internalGetApiKeySecuritySchemeFieldBuilder().getBuilder(), - extensionRegistry); - schemeCase_ = 1; - break; - } // case 10 - case 18: { - input.readMessage( - internalGetHttpAuthSecuritySchemeFieldBuilder().getBuilder(), - extensionRegistry); - schemeCase_ = 2; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetOauth2SecuritySchemeFieldBuilder().getBuilder(), - extensionRegistry); - schemeCase_ = 3; - break; - } // case 26 - case 34: { - input.readMessage( - internalGetOpenIdConnectSecuritySchemeFieldBuilder().getBuilder(), - extensionRegistry); - schemeCase_ = 4; - break; - } // case 34 - case 42: { - input.readMessage( - internalGetMtlsSecuritySchemeFieldBuilder().getBuilder(), - extensionRegistry); - schemeCase_ = 5; - break; - } // case 42 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int schemeCase_ = 0; - private java.lang.Object scheme_; - public SchemeCase - getSchemeCase() { - return SchemeCase.forNumber( - schemeCase_); - } - - public Builder clearScheme() { - schemeCase_ = 0; - scheme_ = null; - onChanged(); - return this; - } - - private int bitField0_; - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.APIKeySecurityScheme, io.a2a.grpc.APIKeySecurityScheme.Builder, io.a2a.grpc.APIKeySecuritySchemeOrBuilder> apiKeySecuritySchemeBuilder_; - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - * @return Whether the apiKeySecurityScheme field is set. - */ - @java.lang.Override - public boolean hasApiKeySecurityScheme() { - return schemeCase_ == 1; - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - * @return The apiKeySecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme() { - if (apiKeySecuritySchemeBuilder_ == null) { - if (schemeCase_ == 1) { - return (io.a2a.grpc.APIKeySecurityScheme) scheme_; - } - return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance(); - } else { - if (schemeCase_ == 1) { - return apiKeySecuritySchemeBuilder_.getMessage(); - } - return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - public Builder setApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) { - if (apiKeySecuritySchemeBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - scheme_ = value; - onChanged(); - } else { - apiKeySecuritySchemeBuilder_.setMessage(value); - } - schemeCase_ = 1; - return this; - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - public Builder setApiKeySecurityScheme( - io.a2a.grpc.APIKeySecurityScheme.Builder builderForValue) { - if (apiKeySecuritySchemeBuilder_ == null) { - scheme_ = builderForValue.build(); - onChanged(); - } else { - apiKeySecuritySchemeBuilder_.setMessage(builderForValue.build()); - } - schemeCase_ = 1; - return this; - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - public Builder mergeApiKeySecurityScheme(io.a2a.grpc.APIKeySecurityScheme value) { - if (apiKeySecuritySchemeBuilder_ == null) { - if (schemeCase_ == 1 && - scheme_ != io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance()) { - scheme_ = io.a2a.grpc.APIKeySecurityScheme.newBuilder((io.a2a.grpc.APIKeySecurityScheme) scheme_) - .mergeFrom(value).buildPartial(); - } else { - scheme_ = value; - } - onChanged(); - } else { - if (schemeCase_ == 1) { - apiKeySecuritySchemeBuilder_.mergeFrom(value); - } else { - apiKeySecuritySchemeBuilder_.setMessage(value); - } - } - schemeCase_ = 1; - return this; - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - public Builder clearApiKeySecurityScheme() { - if (apiKeySecuritySchemeBuilder_ == null) { - if (schemeCase_ == 1) { - schemeCase_ = 0; - scheme_ = null; - onChanged(); - } - } else { - if (schemeCase_ == 1) { - schemeCase_ = 0; - scheme_ = null; - } - apiKeySecuritySchemeBuilder_.clear(); - } - return this; - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - public io.a2a.grpc.APIKeySecurityScheme.Builder getApiKeySecuritySchemeBuilder() { - return internalGetApiKeySecuritySchemeFieldBuilder().getBuilder(); - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - @java.lang.Override - public io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder() { - if ((schemeCase_ == 1) && (apiKeySecuritySchemeBuilder_ != null)) { - return apiKeySecuritySchemeBuilder_.getMessageOrBuilder(); - } else { - if (schemeCase_ == 1) { - return (io.a2a.grpc.APIKeySecurityScheme) scheme_; - } - return io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * API key-based authentication.
-     * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.APIKeySecurityScheme, io.a2a.grpc.APIKeySecurityScheme.Builder, io.a2a.grpc.APIKeySecuritySchemeOrBuilder> - internalGetApiKeySecuritySchemeFieldBuilder() { - if (apiKeySecuritySchemeBuilder_ == null) { - if (!(schemeCase_ == 1)) { - scheme_ = io.a2a.grpc.APIKeySecurityScheme.getDefaultInstance(); - } - apiKeySecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.APIKeySecurityScheme, io.a2a.grpc.APIKeySecurityScheme.Builder, io.a2a.grpc.APIKeySecuritySchemeOrBuilder>( - (io.a2a.grpc.APIKeySecurityScheme) scheme_, - getParentForChildren(), - isClean()); - scheme_ = null; - } - schemeCase_ = 1; - onChanged(); - return apiKeySecuritySchemeBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.HTTPAuthSecurityScheme, io.a2a.grpc.HTTPAuthSecurityScheme.Builder, io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder> httpAuthSecuritySchemeBuilder_; - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - * @return Whether the httpAuthSecurityScheme field is set. - */ - @java.lang.Override - public boolean hasHttpAuthSecurityScheme() { - return schemeCase_ == 2; - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - * @return The httpAuthSecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme() { - if (httpAuthSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 2) { - return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_; - } - return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); - } else { - if (schemeCase_ == 2) { - return httpAuthSecuritySchemeBuilder_.getMessage(); - } - return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - public Builder setHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme value) { - if (httpAuthSecuritySchemeBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - scheme_ = value; - onChanged(); - } else { - httpAuthSecuritySchemeBuilder_.setMessage(value); - } - schemeCase_ = 2; - return this; - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - public Builder setHttpAuthSecurityScheme( - io.a2a.grpc.HTTPAuthSecurityScheme.Builder builderForValue) { - if (httpAuthSecuritySchemeBuilder_ == null) { - scheme_ = builderForValue.build(); - onChanged(); - } else { - httpAuthSecuritySchemeBuilder_.setMessage(builderForValue.build()); - } - schemeCase_ = 2; - return this; - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - public Builder mergeHttpAuthSecurityScheme(io.a2a.grpc.HTTPAuthSecurityScheme value) { - if (httpAuthSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 2 && - scheme_ != io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance()) { - scheme_ = io.a2a.grpc.HTTPAuthSecurityScheme.newBuilder((io.a2a.grpc.HTTPAuthSecurityScheme) scheme_) - .mergeFrom(value).buildPartial(); - } else { - scheme_ = value; - } - onChanged(); - } else { - if (schemeCase_ == 2) { - httpAuthSecuritySchemeBuilder_.mergeFrom(value); - } else { - httpAuthSecuritySchemeBuilder_.setMessage(value); - } - } - schemeCase_ = 2; - return this; - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - public Builder clearHttpAuthSecurityScheme() { - if (httpAuthSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 2) { - schemeCase_ = 0; - scheme_ = null; - onChanged(); - } - } else { - if (schemeCase_ == 2) { - schemeCase_ = 0; - scheme_ = null; - } - httpAuthSecuritySchemeBuilder_.clear(); - } - return this; - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - public io.a2a.grpc.HTTPAuthSecurityScheme.Builder getHttpAuthSecuritySchemeBuilder() { - return internalGetHttpAuthSecuritySchemeFieldBuilder().getBuilder(); - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - @java.lang.Override - public io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder() { - if ((schemeCase_ == 2) && (httpAuthSecuritySchemeBuilder_ != null)) { - return httpAuthSecuritySchemeBuilder_.getMessageOrBuilder(); - } else { - if (schemeCase_ == 2) { - return (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_; - } - return io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * HTTP authentication (Basic, Bearer, etc.).
-     * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.HTTPAuthSecurityScheme, io.a2a.grpc.HTTPAuthSecurityScheme.Builder, io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder> - internalGetHttpAuthSecuritySchemeFieldBuilder() { - if (httpAuthSecuritySchemeBuilder_ == null) { - if (!(schemeCase_ == 2)) { - scheme_ = io.a2a.grpc.HTTPAuthSecurityScheme.getDefaultInstance(); - } - httpAuthSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.HTTPAuthSecurityScheme, io.a2a.grpc.HTTPAuthSecurityScheme.Builder, io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder>( - (io.a2a.grpc.HTTPAuthSecurityScheme) scheme_, - getParentForChildren(), - isClean()); - scheme_ = null; - } - schemeCase_ = 2; - onChanged(); - return httpAuthSecuritySchemeBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OAuth2SecurityScheme, io.a2a.grpc.OAuth2SecurityScheme.Builder, io.a2a.grpc.OAuth2SecuritySchemeOrBuilder> oauth2SecuritySchemeBuilder_; - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - * @return Whether the oauth2SecurityScheme field is set. - */ - @java.lang.Override - public boolean hasOauth2SecurityScheme() { - return schemeCase_ == 3; - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - * @return The oauth2SecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme() { - if (oauth2SecuritySchemeBuilder_ == null) { - if (schemeCase_ == 3) { - return (io.a2a.grpc.OAuth2SecurityScheme) scheme_; - } - return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance(); - } else { - if (schemeCase_ == 3) { - return oauth2SecuritySchemeBuilder_.getMessage(); - } - return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - public Builder setOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) { - if (oauth2SecuritySchemeBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - scheme_ = value; - onChanged(); - } else { - oauth2SecuritySchemeBuilder_.setMessage(value); - } - schemeCase_ = 3; - return this; - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - public Builder setOauth2SecurityScheme( - io.a2a.grpc.OAuth2SecurityScheme.Builder builderForValue) { - if (oauth2SecuritySchemeBuilder_ == null) { - scheme_ = builderForValue.build(); - onChanged(); - } else { - oauth2SecuritySchemeBuilder_.setMessage(builderForValue.build()); - } - schemeCase_ = 3; - return this; - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - public Builder mergeOauth2SecurityScheme(io.a2a.grpc.OAuth2SecurityScheme value) { - if (oauth2SecuritySchemeBuilder_ == null) { - if (schemeCase_ == 3 && - scheme_ != io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance()) { - scheme_ = io.a2a.grpc.OAuth2SecurityScheme.newBuilder((io.a2a.grpc.OAuth2SecurityScheme) scheme_) - .mergeFrom(value).buildPartial(); - } else { - scheme_ = value; - } - onChanged(); - } else { - if (schemeCase_ == 3) { - oauth2SecuritySchemeBuilder_.mergeFrom(value); - } else { - oauth2SecuritySchemeBuilder_.setMessage(value); - } - } - schemeCase_ = 3; - return this; - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - public Builder clearOauth2SecurityScheme() { - if (oauth2SecuritySchemeBuilder_ == null) { - if (schemeCase_ == 3) { - schemeCase_ = 0; - scheme_ = null; - onChanged(); - } - } else { - if (schemeCase_ == 3) { - schemeCase_ = 0; - scheme_ = null; - } - oauth2SecuritySchemeBuilder_.clear(); - } - return this; - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - public io.a2a.grpc.OAuth2SecurityScheme.Builder getOauth2SecuritySchemeBuilder() { - return internalGetOauth2SecuritySchemeFieldBuilder().getBuilder(); - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - @java.lang.Override - public io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder() { - if ((schemeCase_ == 3) && (oauth2SecuritySchemeBuilder_ != null)) { - return oauth2SecuritySchemeBuilder_.getMessageOrBuilder(); - } else { - if (schemeCase_ == 3) { - return (io.a2a.grpc.OAuth2SecurityScheme) scheme_; - } - return io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * OAuth 2.0 authentication.
-     * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OAuth2SecurityScheme, io.a2a.grpc.OAuth2SecurityScheme.Builder, io.a2a.grpc.OAuth2SecuritySchemeOrBuilder> - internalGetOauth2SecuritySchemeFieldBuilder() { - if (oauth2SecuritySchemeBuilder_ == null) { - if (!(schemeCase_ == 3)) { - scheme_ = io.a2a.grpc.OAuth2SecurityScheme.getDefaultInstance(); - } - oauth2SecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OAuth2SecurityScheme, io.a2a.grpc.OAuth2SecurityScheme.Builder, io.a2a.grpc.OAuth2SecuritySchemeOrBuilder>( - (io.a2a.grpc.OAuth2SecurityScheme) scheme_, - getParentForChildren(), - isClean()); - scheme_ = null; - } - schemeCase_ = 3; - onChanged(); - return oauth2SecuritySchemeBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OpenIdConnectSecurityScheme, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder, io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder> openIdConnectSecuritySchemeBuilder_; - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - * @return Whether the openIdConnectSecurityScheme field is set. - */ - @java.lang.Override - public boolean hasOpenIdConnectSecurityScheme() { - return schemeCase_ == 4; - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - * @return The openIdConnectSecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme() { - if (openIdConnectSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 4) { - return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_; - } - return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); - } else { - if (schemeCase_ == 4) { - return openIdConnectSecuritySchemeBuilder_.getMessage(); - } - return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - public Builder setOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityScheme value) { - if (openIdConnectSecuritySchemeBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - scheme_ = value; - onChanged(); - } else { - openIdConnectSecuritySchemeBuilder_.setMessage(value); - } - schemeCase_ = 4; - return this; - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - public Builder setOpenIdConnectSecurityScheme( - io.a2a.grpc.OpenIdConnectSecurityScheme.Builder builderForValue) { - if (openIdConnectSecuritySchemeBuilder_ == null) { - scheme_ = builderForValue.build(); - onChanged(); - } else { - openIdConnectSecuritySchemeBuilder_.setMessage(builderForValue.build()); - } - schemeCase_ = 4; - return this; - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - public Builder mergeOpenIdConnectSecurityScheme(io.a2a.grpc.OpenIdConnectSecurityScheme value) { - if (openIdConnectSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 4 && - scheme_ != io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance()) { - scheme_ = io.a2a.grpc.OpenIdConnectSecurityScheme.newBuilder((io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_) - .mergeFrom(value).buildPartial(); - } else { - scheme_ = value; - } - onChanged(); - } else { - if (schemeCase_ == 4) { - openIdConnectSecuritySchemeBuilder_.mergeFrom(value); - } else { - openIdConnectSecuritySchemeBuilder_.setMessage(value); - } - } - schemeCase_ = 4; - return this; - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - public Builder clearOpenIdConnectSecurityScheme() { - if (openIdConnectSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 4) { - schemeCase_ = 0; - scheme_ = null; - onChanged(); - } - } else { - if (schemeCase_ == 4) { - schemeCase_ = 0; - scheme_ = null; - } - openIdConnectSecuritySchemeBuilder_.clear(); - } - return this; - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - public io.a2a.grpc.OpenIdConnectSecurityScheme.Builder getOpenIdConnectSecuritySchemeBuilder() { - return internalGetOpenIdConnectSecuritySchemeFieldBuilder().getBuilder(); - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - @java.lang.Override - public io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder() { - if ((schemeCase_ == 4) && (openIdConnectSecuritySchemeBuilder_ != null)) { - return openIdConnectSecuritySchemeBuilder_.getMessageOrBuilder(); - } else { - if (schemeCase_ == 4) { - return (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_; - } - return io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * OpenID Connect authentication.
-     * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OpenIdConnectSecurityScheme, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder, io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder> - internalGetOpenIdConnectSecuritySchemeFieldBuilder() { - if (openIdConnectSecuritySchemeBuilder_ == null) { - if (!(schemeCase_ == 4)) { - scheme_ = io.a2a.grpc.OpenIdConnectSecurityScheme.getDefaultInstance(); - } - openIdConnectSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.OpenIdConnectSecurityScheme, io.a2a.grpc.OpenIdConnectSecurityScheme.Builder, io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder>( - (io.a2a.grpc.OpenIdConnectSecurityScheme) scheme_, - getParentForChildren(), - isClean()); - scheme_ = null; - } - schemeCase_ = 4; - onChanged(); - return openIdConnectSecuritySchemeBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.MutualTlsSecurityScheme, io.a2a.grpc.MutualTlsSecurityScheme.Builder, io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder> mtlsSecuritySchemeBuilder_; - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - * @return Whether the mtlsSecurityScheme field is set. - */ - @java.lang.Override - public boolean hasMtlsSecurityScheme() { - return schemeCase_ == 5; - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - * @return The mtlsSecurityScheme. - */ - @java.lang.Override - public io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme() { - if (mtlsSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 5) { - return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_; - } - return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance(); - } else { - if (schemeCase_ == 5) { - return mtlsSecuritySchemeBuilder_.getMessage(); - } - return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - public Builder setMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value) { - if (mtlsSecuritySchemeBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - scheme_ = value; - onChanged(); - } else { - mtlsSecuritySchemeBuilder_.setMessage(value); - } - schemeCase_ = 5; - return this; - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - public Builder setMtlsSecurityScheme( - io.a2a.grpc.MutualTlsSecurityScheme.Builder builderForValue) { - if (mtlsSecuritySchemeBuilder_ == null) { - scheme_ = builderForValue.build(); - onChanged(); - } else { - mtlsSecuritySchemeBuilder_.setMessage(builderForValue.build()); - } - schemeCase_ = 5; - return this; - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - public Builder mergeMtlsSecurityScheme(io.a2a.grpc.MutualTlsSecurityScheme value) { - if (mtlsSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 5 && - scheme_ != io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance()) { - scheme_ = io.a2a.grpc.MutualTlsSecurityScheme.newBuilder((io.a2a.grpc.MutualTlsSecurityScheme) scheme_) - .mergeFrom(value).buildPartial(); - } else { - scheme_ = value; - } - onChanged(); - } else { - if (schemeCase_ == 5) { - mtlsSecuritySchemeBuilder_.mergeFrom(value); - } else { - mtlsSecuritySchemeBuilder_.setMessage(value); - } - } - schemeCase_ = 5; - return this; - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - public Builder clearMtlsSecurityScheme() { - if (mtlsSecuritySchemeBuilder_ == null) { - if (schemeCase_ == 5) { - schemeCase_ = 0; - scheme_ = null; - onChanged(); - } - } else { - if (schemeCase_ == 5) { - schemeCase_ = 0; - scheme_ = null; - } - mtlsSecuritySchemeBuilder_.clear(); - } - return this; - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - public io.a2a.grpc.MutualTlsSecurityScheme.Builder getMtlsSecuritySchemeBuilder() { - return internalGetMtlsSecuritySchemeFieldBuilder().getBuilder(); - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - @java.lang.Override - public io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder() { - if ((schemeCase_ == 5) && (mtlsSecuritySchemeBuilder_ != null)) { - return mtlsSecuritySchemeBuilder_.getMessageOrBuilder(); - } else { - if (schemeCase_ == 5) { - return (io.a2a.grpc.MutualTlsSecurityScheme) scheme_; - } - return io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance(); - } - } - /** - *
-     * Mutual TLS authentication.
-     * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.MutualTlsSecurityScheme, io.a2a.grpc.MutualTlsSecurityScheme.Builder, io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder> - internalGetMtlsSecuritySchemeFieldBuilder() { - if (mtlsSecuritySchemeBuilder_ == null) { - if (!(schemeCase_ == 5)) { - scheme_ = io.a2a.grpc.MutualTlsSecurityScheme.getDefaultInstance(); - } - mtlsSecuritySchemeBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.MutualTlsSecurityScheme, io.a2a.grpc.MutualTlsSecurityScheme.Builder, io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder>( - (io.a2a.grpc.MutualTlsSecurityScheme) scheme_, - getParentForChildren(), - isClean()); - scheme_ = null; - } - schemeCase_ = 5; - onChanged(); - return mtlsSecuritySchemeBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.SecurityScheme) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.SecurityScheme) - private static final io.a2a.grpc.SecurityScheme DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.SecurityScheme(); - } - - public static io.a2a.grpc.SecurityScheme getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public SecurityScheme parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.SecurityScheme getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java deleted file mode 100644 index 6a5d92b7c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SecuritySchemeOrBuilder.java +++ /dev/null @@ -1,149 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface SecuritySchemeOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SecurityScheme) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * API key-based authentication.
-   * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - * @return Whether the apiKeySecurityScheme field is set. - */ - boolean hasApiKeySecurityScheme(); - /** - *
-   * API key-based authentication.
-   * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - * @return The apiKeySecurityScheme. - */ - io.a2a.grpc.APIKeySecurityScheme getApiKeySecurityScheme(); - /** - *
-   * API key-based authentication.
-   * 
- * - * .a2a.v1.APIKeySecurityScheme api_key_security_scheme = 1; - */ - io.a2a.grpc.APIKeySecuritySchemeOrBuilder getApiKeySecuritySchemeOrBuilder(); - - /** - *
-   * HTTP authentication (Basic, Bearer, etc.).
-   * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - * @return Whether the httpAuthSecurityScheme field is set. - */ - boolean hasHttpAuthSecurityScheme(); - /** - *
-   * HTTP authentication (Basic, Bearer, etc.).
-   * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - * @return The httpAuthSecurityScheme. - */ - io.a2a.grpc.HTTPAuthSecurityScheme getHttpAuthSecurityScheme(); - /** - *
-   * HTTP authentication (Basic, Bearer, etc.).
-   * 
- * - * .a2a.v1.HTTPAuthSecurityScheme http_auth_security_scheme = 2; - */ - io.a2a.grpc.HTTPAuthSecuritySchemeOrBuilder getHttpAuthSecuritySchemeOrBuilder(); - - /** - *
-   * OAuth 2.0 authentication.
-   * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - * @return Whether the oauth2SecurityScheme field is set. - */ - boolean hasOauth2SecurityScheme(); - /** - *
-   * OAuth 2.0 authentication.
-   * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - * @return The oauth2SecurityScheme. - */ - io.a2a.grpc.OAuth2SecurityScheme getOauth2SecurityScheme(); - /** - *
-   * OAuth 2.0 authentication.
-   * 
- * - * .a2a.v1.OAuth2SecurityScheme oauth2_security_scheme = 3; - */ - io.a2a.grpc.OAuth2SecuritySchemeOrBuilder getOauth2SecuritySchemeOrBuilder(); - - /** - *
-   * OpenID Connect authentication.
-   * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - * @return Whether the openIdConnectSecurityScheme field is set. - */ - boolean hasOpenIdConnectSecurityScheme(); - /** - *
-   * OpenID Connect authentication.
-   * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - * @return The openIdConnectSecurityScheme. - */ - io.a2a.grpc.OpenIdConnectSecurityScheme getOpenIdConnectSecurityScheme(); - /** - *
-   * OpenID Connect authentication.
-   * 
- * - * .a2a.v1.OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - */ - io.a2a.grpc.OpenIdConnectSecuritySchemeOrBuilder getOpenIdConnectSecuritySchemeOrBuilder(); - - /** - *
-   * Mutual TLS authentication.
-   * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - * @return Whether the mtlsSecurityScheme field is set. - */ - boolean hasMtlsSecurityScheme(); - /** - *
-   * Mutual TLS authentication.
-   * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - * @return The mtlsSecurityScheme. - */ - io.a2a.grpc.MutualTlsSecurityScheme getMtlsSecurityScheme(); - /** - *
-   * Mutual TLS authentication.
-   * 
- * - * .a2a.v1.MutualTlsSecurityScheme mtls_security_scheme = 5; - */ - io.a2a.grpc.MutualTlsSecuritySchemeOrBuilder getMtlsSecuritySchemeOrBuilder(); - - io.a2a.grpc.SecurityScheme.SchemeCase getSchemeCase(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java deleted file mode 100644 index 57374039f..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfiguration.java +++ /dev/null @@ -1,1071 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:SendMessageConfiguration]
- * Configuration of a send message request.
- * 
- * - * Protobuf type {@code a2a.v1.SendMessageConfiguration} - */ -@com.google.protobuf.Generated -public final class SendMessageConfiguration extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageConfiguration) - SendMessageConfigurationOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "SendMessageConfiguration"); - } - // Use SendMessageConfiguration.newBuilder() to construct. - private SendMessageConfiguration(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private SendMessageConfiguration() { - acceptedOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SendMessageConfiguration.class, io.a2a.grpc.SendMessageConfiguration.Builder.class); - } - - private int bitField0_; - public static final int ACCEPTED_OUTPUT_MODES_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList acceptedOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @return A list containing the acceptedOutputModes. - */ - public com.google.protobuf.ProtocolStringList - getAcceptedOutputModesList() { - return acceptedOutputModes_; - } - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @return The count of acceptedOutputModes. - */ - public int getAcceptedOutputModesCount() { - return acceptedOutputModes_.size(); - } - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @param index The index of the element to return. - * @return The acceptedOutputModes at the given index. - */ - public java.lang.String getAcceptedOutputModes(int index) { - return acceptedOutputModes_.get(index); - } - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @param index The index of the value to return. - * @return The bytes of the acceptedOutputModes at the given index. - */ - public com.google.protobuf.ByteString - getAcceptedOutputModesBytes(int index) { - return acceptedOutputModes_.getByteString(index); - } - - public static final int PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 2; - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; - /** - *
-   * Configuration for the agent to send push notifications for task updates.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return Whether the pushNotificationConfig field is set. - */ - @java.lang.Override - public boolean hasPushNotificationConfig() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * Configuration for the agent to send push notifications for task updates.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return The pushNotificationConfig. - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } - /** - *
-   * Configuration for the agent to send push notifications for task updates.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } - - public static final int HISTORY_LENGTH_FIELD_NUMBER = 3; - private int historyLength_ = 0; - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve in
-   * the response. An unset value means the client does not impose any limit. A
-   * value of zero is a request to not include any messages. The server MUST NOT
-   * return more messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 3; - * @return Whether the historyLength field is set. - */ - @java.lang.Override - public boolean hasHistoryLength() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve in
-   * the response. An unset value means the client does not impose any limit. A
-   * value of zero is a request to not include any messages. The server MUST NOT
-   * return more messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 3; - * @return The historyLength. - */ - @java.lang.Override - public int getHistoryLength() { - return historyLength_; - } - - public static final int BLOCKING_FIELD_NUMBER = 4; - private boolean blocking_ = false; - /** - *
-   * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
-   * 
- * - * bool blocking = 4; - * @return The blocking. - */ - @java.lang.Override - public boolean getBlocking() { - return blocking_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - for (int i = 0; i < acceptedOutputModes_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, acceptedOutputModes_.getRaw(i)); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(2, getPushNotificationConfig()); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeInt32(3, historyLength_); - } - if (blocking_ != false) { - output.writeBool(4, blocking_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - { - int dataSize = 0; - for (int i = 0; i < acceptedOutputModes_.size(); i++) { - dataSize += computeStringSizeNoTag(acceptedOutputModes_.getRaw(i)); - } - size += dataSize; - size += 1 * getAcceptedOutputModesList().size(); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getPushNotificationConfig()); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, historyLength_); - } - if (blocking_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(4, blocking_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.SendMessageConfiguration)) { - return super.equals(obj); - } - io.a2a.grpc.SendMessageConfiguration other = (io.a2a.grpc.SendMessageConfiguration) obj; - - if (!getAcceptedOutputModesList() - .equals(other.getAcceptedOutputModesList())) return false; - if (hasPushNotificationConfig() != other.hasPushNotificationConfig()) return false; - if (hasPushNotificationConfig()) { - if (!getPushNotificationConfig() - .equals(other.getPushNotificationConfig())) return false; - } - if (hasHistoryLength() != other.hasHistoryLength()) return false; - if (hasHistoryLength()) { - if (getHistoryLength() - != other.getHistoryLength()) return false; - } - if (getBlocking() - != other.getBlocking()) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (getAcceptedOutputModesCount() > 0) { - hash = (37 * hash) + ACCEPTED_OUTPUT_MODES_FIELD_NUMBER; - hash = (53 * hash) + getAcceptedOutputModesList().hashCode(); - } - if (hasPushNotificationConfig()) { - hash = (37 * hash) + PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER; - hash = (53 * hash) + getPushNotificationConfig().hashCode(); - } - if (hasHistoryLength()) { - hash = (37 * hash) + HISTORY_LENGTH_FIELD_NUMBER; - hash = (53 * hash) + getHistoryLength(); - } - hash = (37 * hash) + BLOCKING_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getBlocking()); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.SendMessageConfiguration parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.SendMessageConfiguration parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SendMessageConfiguration parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.SendMessageConfiguration prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:SendMessageConfiguration]
-   * Configuration of a send message request.
-   * 
- * - * Protobuf type {@code a2a.v1.SendMessageConfiguration} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageConfiguration) - io.a2a.grpc.SendMessageConfigurationOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SendMessageConfiguration.class, io.a2a.grpc.SendMessageConfiguration.Builder.class); - } - - // Construct using io.a2a.grpc.SendMessageConfiguration.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetPushNotificationConfigFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - acceptedOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; - } - historyLength_ = 0; - blocking_ = false; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageConfiguration_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageConfiguration getDefaultInstanceForType() { - return io.a2a.grpc.SendMessageConfiguration.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.SendMessageConfiguration build() { - io.a2a.grpc.SendMessageConfiguration result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageConfiguration buildPartial() { - io.a2a.grpc.SendMessageConfiguration result = new io.a2a.grpc.SendMessageConfiguration(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.SendMessageConfiguration result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - acceptedOutputModes_.makeImmutable(); - result.acceptedOutputModes_ = acceptedOutputModes_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000002) != 0)) { - result.pushNotificationConfig_ = pushNotificationConfigBuilder_ == null - ? pushNotificationConfig_ - : pushNotificationConfigBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.historyLength_ = historyLength_; - to_bitField0_ |= 0x00000002; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.blocking_ = blocking_; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.SendMessageConfiguration) { - return mergeFrom((io.a2a.grpc.SendMessageConfiguration)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.SendMessageConfiguration other) { - if (other == io.a2a.grpc.SendMessageConfiguration.getDefaultInstance()) return this; - if (!other.acceptedOutputModes_.isEmpty()) { - if (acceptedOutputModes_.isEmpty()) { - acceptedOutputModes_ = other.acceptedOutputModes_; - bitField0_ |= 0x00000001; - } else { - ensureAcceptedOutputModesIsMutable(); - acceptedOutputModes_.addAll(other.acceptedOutputModes_); - } - onChanged(); - } - if (other.hasPushNotificationConfig()) { - mergePushNotificationConfig(other.getPushNotificationConfig()); - } - if (other.hasHistoryLength()) { - setHistoryLength(other.getHistoryLength()); - } - if (other.getBlocking() != false) { - setBlocking(other.getBlocking()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - java.lang.String s = input.readStringRequireUtf8(); - ensureAcceptedOutputModesIsMutable(); - acceptedOutputModes_.add(s); - break; - } // case 10 - case 18: { - input.readMessage( - internalGetPushNotificationConfigFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 24: { - historyLength_ = input.readInt32(); - bitField0_ |= 0x00000004; - break; - } // case 24 - case 32: { - blocking_ = input.readBool(); - bitField0_ |= 0x00000008; - break; - } // case 32 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private com.google.protobuf.LazyStringArrayList acceptedOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureAcceptedOutputModesIsMutable() { - if (!acceptedOutputModes_.isModifiable()) { - acceptedOutputModes_ = new com.google.protobuf.LazyStringArrayList(acceptedOutputModes_); - } - bitField0_ |= 0x00000001; - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @return A list containing the acceptedOutputModes. - */ - public com.google.protobuf.ProtocolStringList - getAcceptedOutputModesList() { - acceptedOutputModes_.makeImmutable(); - return acceptedOutputModes_; - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @return The count of acceptedOutputModes. - */ - public int getAcceptedOutputModesCount() { - return acceptedOutputModes_.size(); - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @param index The index of the element to return. - * @return The acceptedOutputModes at the given index. - */ - public java.lang.String getAcceptedOutputModes(int index) { - return acceptedOutputModes_.get(index); - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @param index The index of the value to return. - * @return The bytes of the acceptedOutputModes at the given index. - */ - public com.google.protobuf.ByteString - getAcceptedOutputModesBytes(int index) { - return acceptedOutputModes_.getByteString(index); - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @param index The index to set the value at. - * @param value The acceptedOutputModes to set. - * @return This builder for chaining. - */ - public Builder setAcceptedOutputModes( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureAcceptedOutputModesIsMutable(); - acceptedOutputModes_.set(index, value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @param value The acceptedOutputModes to add. - * @return This builder for chaining. - */ - public Builder addAcceptedOutputModes( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureAcceptedOutputModesIsMutable(); - acceptedOutputModes_.add(value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @param values The acceptedOutputModes to add. - * @return This builder for chaining. - */ - public Builder addAllAcceptedOutputModes( - java.lang.Iterable values) { - ensureAcceptedOutputModesIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, acceptedOutputModes_); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @return This builder for chaining. - */ - public Builder clearAcceptedOutputModes() { - acceptedOutputModes_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001);; - onChanged(); - return this; - } - /** - *
-     * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-     * 
- * - * repeated string accepted_output_modes = 1; - * @param value The bytes of the acceptedOutputModes to add. - * @return This builder for chaining. - */ - public Builder addAcceptedOutputModesBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureAcceptedOutputModesIsMutable(); - acceptedOutputModes_.add(value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> pushNotificationConfigBuilder_; - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return Whether the pushNotificationConfig field is set. - */ - public boolean hasPushNotificationConfig() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return The pushNotificationConfig. - */ - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - if (pushNotificationConfigBuilder_ == null) { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } else { - return pushNotificationConfigBuilder_.getMessage(); - } - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - pushNotificationConfig_ = value; - } else { - pushNotificationConfigBuilder_.setMessage(value); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - public Builder setPushNotificationConfig( - io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfig_ = builderForValue.build(); - } else { - pushNotificationConfigBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { - if (((bitField0_ & 0x00000002) != 0) && - pushNotificationConfig_ != null && - pushNotificationConfig_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { - getPushNotificationConfigBuilder().mergeFrom(value); - } else { - pushNotificationConfig_ = value; - } - } else { - pushNotificationConfigBuilder_.mergeFrom(value); - } - if (pushNotificationConfig_ != null) { - bitField0_ |= 0x00000002; - onChanged(); - } - return this; - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - public Builder clearPushNotificationConfig() { - bitField0_ = (bitField0_ & ~0x00000002); - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() { - bitField0_ |= 0x00000002; - onChanged(); - return internalGetPushNotificationConfigFieldBuilder().getBuilder(); - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - if (pushNotificationConfigBuilder_ != null) { - return pushNotificationConfigBuilder_.getMessageOrBuilder(); - } else { - return pushNotificationConfig_ == null ? - io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } - } - /** - *
-     * Configuration for the agent to send push notifications for task updates.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> - internalGetPushNotificationConfigFieldBuilder() { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfigBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder>( - getPushNotificationConfig(), - getParentForChildren(), - isClean()); - pushNotificationConfig_ = null; - } - return pushNotificationConfigBuilder_; - } - - private int historyLength_ ; - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve in
-     * the response. An unset value means the client does not impose any limit. A
-     * value of zero is a request to not include any messages. The server MUST NOT
-     * return more messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 3; - * @return Whether the historyLength field is set. - */ - @java.lang.Override - public boolean hasHistoryLength() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve in
-     * the response. An unset value means the client does not impose any limit. A
-     * value of zero is a request to not include any messages. The server MUST NOT
-     * return more messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 3; - * @return The historyLength. - */ - @java.lang.Override - public int getHistoryLength() { - return historyLength_; - } - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve in
-     * the response. An unset value means the client does not impose any limit. A
-     * value of zero is a request to not include any messages. The server MUST NOT
-     * return more messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 3; - * @param value The historyLength to set. - * @return This builder for chaining. - */ - public Builder setHistoryLength(int value) { - - historyLength_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The maximum number of most recent messages from the task's history to retrieve in
-     * the response. An unset value means the client does not impose any limit. A
-     * value of zero is a request to not include any messages. The server MUST NOT
-     * return more messages than the provided value, but MAY apply a lower limit.
-     * 
- * - * optional int32 history_length = 3; - * @return This builder for chaining. - */ - public Builder clearHistoryLength() { - bitField0_ = (bitField0_ & ~0x00000004); - historyLength_ = 0; - onChanged(); - return this; - } - - private boolean blocking_ ; - /** - *
-     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
-     * 
- * - * bool blocking = 4; - * @return The blocking. - */ - @java.lang.Override - public boolean getBlocking() { - return blocking_; - } - /** - *
-     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
-     * 
- * - * bool blocking = 4; - * @param value The blocking to set. - * @return This builder for chaining. - */ - public Builder setBlocking(boolean value) { - - blocking_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
-     * 
- * - * bool blocking = 4; - * @return This builder for chaining. - */ - public Builder clearBlocking() { - bitField0_ = (bitField0_ & ~0x00000008); - blocking_ = false; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageConfiguration) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageConfiguration) - private static final io.a2a.grpc.SendMessageConfiguration DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageConfiguration(); - } - - public static io.a2a.grpc.SendMessageConfiguration getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public SendMessageConfiguration parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageConfiguration getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java deleted file mode 100644 index a9e9fc401..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageConfigurationOrBuilder.java +++ /dev/null @@ -1,115 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface SendMessageConfigurationOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageConfiguration) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @return A list containing the acceptedOutputModes. - */ - java.util.List - getAcceptedOutputModesList(); - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @return The count of acceptedOutputModes. - */ - int getAcceptedOutputModesCount(); - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @param index The index of the element to return. - * @return The acceptedOutputModes at the given index. - */ - java.lang.String getAcceptedOutputModes(int index); - /** - *
-   * A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output.
-   * 
- * - * repeated string accepted_output_modes = 1; - * @param index The index of the value to return. - * @return The bytes of the acceptedOutputModes at the given index. - */ - com.google.protobuf.ByteString - getAcceptedOutputModesBytes(int index); - - /** - *
-   * Configuration for the agent to send push notifications for task updates.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return Whether the pushNotificationConfig field is set. - */ - boolean hasPushNotificationConfig(); - /** - *
-   * Configuration for the agent to send push notifications for task updates.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - * @return The pushNotificationConfig. - */ - io.a2a.grpc.PushNotificationConfig getPushNotificationConfig(); - /** - *
-   * Configuration for the agent to send push notifications for task updates.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2; - */ - io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder(); - - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve in
-   * the response. An unset value means the client does not impose any limit. A
-   * value of zero is a request to not include any messages. The server MUST NOT
-   * return more messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 3; - * @return Whether the historyLength field is set. - */ - boolean hasHistoryLength(); - /** - *
-   * The maximum number of most recent messages from the task's history to retrieve in
-   * the response. An unset value means the client does not impose any limit. A
-   * value of zero is a request to not include any messages. The server MUST NOT
-   * return more messages than the provided value, but MAY apply a lower limit.
-   * 
- * - * optional int32 history_length = 3; - * @return The historyLength. - */ - int getHistoryLength(); - - /** - *
-   * If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false.
-   * 
- * - * bool blocking = 4; - * @return The blocking. - */ - boolean getBlocking(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java deleted file mode 100644 index 943fc6067..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequest.java +++ /dev/null @@ -1,1249 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * /////////// Request Messages ///////////
- * --8<-- [start:SendMessageRequest]
- * Represents a request for the `SendMessage` method.
- * 
- * - * Protobuf type {@code a2a.v1.SendMessageRequest} - */ -@com.google.protobuf.Generated -public final class SendMessageRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageRequest) - SendMessageRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "SendMessageRequest"); - } - // Use SendMessageRequest.newBuilder() to construct. - private SendMessageRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private SendMessageRequest() { - tenant_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SendMessageRequest.class, io.a2a.grpc.SendMessageRequest.Builder.class); - } - - private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int MESSAGE_FIELD_NUMBER = 1; - private io.a2a.grpc.Message message_; - /** - *
-   * The message to send to the agent.
-   * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the message field is set. - */ - @java.lang.Override - public boolean hasMessage() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The message to send to the agent.
-   * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The message. - */ - @java.lang.Override - public io.a2a.grpc.Message getMessage() { - return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; - } - /** - *
-   * The message to send to the agent.
-   * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; - } - - public static final int CONFIGURATION_FIELD_NUMBER = 2; - private io.a2a.grpc.SendMessageConfiguration configuration_; - /** - *
-   * Configuration for the send request.
-   * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - * @return Whether the configuration field is set. - */ - @java.lang.Override - public boolean hasConfiguration() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * Configuration for the send request.
-   * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - * @return The configuration. - */ - @java.lang.Override - public io.a2a.grpc.SendMessageConfiguration getConfiguration() { - return configuration_ == null ? io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; - } - /** - *
-   * Configuration for the send request.
-   * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - @java.lang.Override - public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() { - return configuration_ == null ? io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; - } - - public static final int METADATA_FIELD_NUMBER = 3; - private com.google.protobuf.Struct metadata_; - /** - *
-   * A flexible key-value map for passing additional context or parameters.
-   * 
- * - * .google.protobuf.Struct metadata = 3; - * @return Whether the metadata field is set. - */ - @java.lang.Override - public boolean hasMetadata() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-   * A flexible key-value map for passing additional context or parameters.
-   * 
- * - * .google.protobuf.Struct metadata = 3; - * @return The metadata. - */ - @java.lang.Override - public com.google.protobuf.Struct getMetadata() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - /** - *
-   * A flexible key-value map for passing additional context or parameters.
-   * 
- * - * .google.protobuf.Struct metadata = 3; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(1, getMessage()); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeMessage(2, getConfiguration()); - } - if (((bitField0_ & 0x00000004) != 0)) { - output.writeMessage(3, getMetadata()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, getMessage()); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getConfiguration()); - } - if (((bitField0_ & 0x00000004) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getMetadata()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.SendMessageRequest)) { - return super.equals(obj); - } - io.a2a.grpc.SendMessageRequest other = (io.a2a.grpc.SendMessageRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (hasMessage() != other.hasMessage()) return false; - if (hasMessage()) { - if (!getMessage() - .equals(other.getMessage())) return false; - } - if (hasConfiguration() != other.hasConfiguration()) return false; - if (hasConfiguration()) { - if (!getConfiguration() - .equals(other.getConfiguration())) return false; - } - if (hasMetadata() != other.hasMetadata()) return false; - if (hasMetadata()) { - if (!getMetadata() - .equals(other.getMetadata())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - if (hasMessage()) { - hash = (37 * hash) + MESSAGE_FIELD_NUMBER; - hash = (53 * hash) + getMessage().hashCode(); - } - if (hasConfiguration()) { - hash = (37 * hash) + CONFIGURATION_FIELD_NUMBER; - hash = (53 * hash) + getConfiguration().hashCode(); - } - if (hasMetadata()) { - hash = (37 * hash) + METADATA_FIELD_NUMBER; - hash = (53 * hash) + getMetadata().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.SendMessageRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SendMessageRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.SendMessageRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.SendMessageRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.SendMessageRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SendMessageRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.SendMessageRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * /////////// Request Messages ///////////
-   * --8<-- [start:SendMessageRequest]
-   * Represents a request for the `SendMessage` method.
-   * 
- * - * Protobuf type {@code a2a.v1.SendMessageRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageRequest) - io.a2a.grpc.SendMessageRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SendMessageRequest.class, io.a2a.grpc.SendMessageRequest.Builder.class); - } - - // Construct using io.a2a.grpc.SendMessageRequest.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetMessageFieldBuilder(); - internalGetConfigurationFieldBuilder(); - internalGetMetadataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - message_ = null; - if (messageBuilder_ != null) { - messageBuilder_.dispose(); - messageBuilder_ = null; - } - configuration_ = null; - if (configurationBuilder_ != null) { - configurationBuilder_.dispose(); - configurationBuilder_ = null; - } - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageRequest getDefaultInstanceForType() { - return io.a2a.grpc.SendMessageRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.SendMessageRequest build() { - io.a2a.grpc.SendMessageRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageRequest buildPartial() { - io.a2a.grpc.SendMessageRequest result = new io.a2a.grpc.SendMessageRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.SendMessageRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000002) != 0)) { - result.message_ = messageBuilder_ == null - ? message_ - : messageBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.configuration_ = configurationBuilder_ == null - ? configuration_ - : configurationBuilder_.build(); - to_bitField0_ |= 0x00000002; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.metadata_ = metadataBuilder_ == null - ? metadata_ - : metadataBuilder_.build(); - to_bitField0_ |= 0x00000004; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.SendMessageRequest) { - return mergeFrom((io.a2a.grpc.SendMessageRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.SendMessageRequest other) { - if (other == io.a2a.grpc.SendMessageRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (other.hasMessage()) { - mergeMessage(other.getMessage()); - } - if (other.hasConfiguration()) { - mergeConfiguration(other.getConfiguration()); - } - if (other.hasMetadata()) { - mergeMetadata(other.getMetadata()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - input.readMessage( - internalGetMessageFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 18: { - input.readMessage( - internalGetConfigurationFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000004; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetMetadataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 26 - case 34: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 4; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private io.a2a.grpc.Message message_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_; - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the message field is set. - */ - public boolean hasMessage() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The message. - */ - public io.a2a.grpc.Message getMessage() { - if (messageBuilder_ == null) { - return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; - } else { - return messageBuilder_.getMessage(); - } - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - message_ = value; - } else { - messageBuilder_.setMessage(value); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setMessage( - io.a2a.grpc.Message.Builder builderForValue) { - if (messageBuilder_ == null) { - message_ = builderForValue.build(); - } else { - messageBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (((bitField0_ & 0x00000002) != 0) && - message_ != null && - message_ != io.a2a.grpc.Message.getDefaultInstance()) { - getMessageBuilder().mergeFrom(value); - } else { - message_ = value; - } - } else { - messageBuilder_.mergeFrom(value); - } - if (message_ != null) { - bitField0_ |= 0x00000002; - onChanged(); - } - return this; - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearMessage() { - bitField0_ = (bitField0_ & ~0x00000002); - message_ = null; - if (messageBuilder_ != null) { - messageBuilder_.dispose(); - messageBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Message.Builder getMessageBuilder() { - bitField0_ |= 0x00000002; - onChanged(); - return internalGetMessageFieldBuilder().getBuilder(); - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - if (messageBuilder_ != null) { - return messageBuilder_.getMessageOrBuilder(); - } else { - return message_ == null ? - io.a2a.grpc.Message.getDefaultInstance() : message_; - } - } - /** - *
-     * The message to send to the agent.
-     * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> - internalGetMessageFieldBuilder() { - if (messageBuilder_ == null) { - messageBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>( - getMessage(), - getParentForChildren(), - isClean()); - message_ = null; - } - return messageBuilder_; - } - - private io.a2a.grpc.SendMessageConfiguration configuration_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.SendMessageConfiguration, io.a2a.grpc.SendMessageConfiguration.Builder, io.a2a.grpc.SendMessageConfigurationOrBuilder> configurationBuilder_; - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - * @return Whether the configuration field is set. - */ - public boolean hasConfiguration() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - * @return The configuration. - */ - public io.a2a.grpc.SendMessageConfiguration getConfiguration() { - if (configurationBuilder_ == null) { - return configuration_ == null ? io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; - } else { - return configurationBuilder_.getMessage(); - } - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - public Builder setConfiguration(io.a2a.grpc.SendMessageConfiguration value) { - if (configurationBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - configuration_ = value; - } else { - configurationBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - public Builder setConfiguration( - io.a2a.grpc.SendMessageConfiguration.Builder builderForValue) { - if (configurationBuilder_ == null) { - configuration_ = builderForValue.build(); - } else { - configurationBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - public Builder mergeConfiguration(io.a2a.grpc.SendMessageConfiguration value) { - if (configurationBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - configuration_ != null && - configuration_ != io.a2a.grpc.SendMessageConfiguration.getDefaultInstance()) { - getConfigurationBuilder().mergeFrom(value); - } else { - configuration_ = value; - } - } else { - configurationBuilder_.mergeFrom(value); - } - if (configuration_ != null) { - bitField0_ |= 0x00000004; - onChanged(); - } - return this; - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - public Builder clearConfiguration() { - bitField0_ = (bitField0_ & ~0x00000004); - configuration_ = null; - if (configurationBuilder_ != null) { - configurationBuilder_.dispose(); - configurationBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - public io.a2a.grpc.SendMessageConfiguration.Builder getConfigurationBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return internalGetConfigurationFieldBuilder().getBuilder(); - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - public io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder() { - if (configurationBuilder_ != null) { - return configurationBuilder_.getMessageOrBuilder(); - } else { - return configuration_ == null ? - io.a2a.grpc.SendMessageConfiguration.getDefaultInstance() : configuration_; - } - } - /** - *
-     * Configuration for the send request.
-     * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.SendMessageConfiguration, io.a2a.grpc.SendMessageConfiguration.Builder, io.a2a.grpc.SendMessageConfigurationOrBuilder> - internalGetConfigurationFieldBuilder() { - if (configurationBuilder_ == null) { - configurationBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.SendMessageConfiguration, io.a2a.grpc.SendMessageConfiguration.Builder, io.a2a.grpc.SendMessageConfigurationOrBuilder>( - getConfiguration(), - getParentForChildren(), - isClean()); - configuration_ = null; - } - return configurationBuilder_; - } - - private com.google.protobuf.Struct metadata_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - * @return Whether the metadata field is set. - */ - public boolean hasMetadata() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - * @return The metadata. - */ - public com.google.protobuf.Struct getMetadata() { - if (metadataBuilder_ == null) { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } else { - return metadataBuilder_.getMessage(); - } - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - */ - public Builder setMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - metadata_ = value; - } else { - metadataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - */ - public Builder setMetadata( - com.google.protobuf.Struct.Builder builderForValue) { - if (metadataBuilder_ == null) { - metadata_ = builderForValue.build(); - } else { - metadataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - */ - public Builder mergeMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - metadata_ != null && - metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { - getMetadataBuilder().mergeFrom(value); - } else { - metadata_ = value; - } - } else { - metadataBuilder_.mergeFrom(value); - } - if (metadata_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - */ - public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000008); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - */ - public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetMetadataFieldBuilder().getBuilder(); - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - */ - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - if (metadataBuilder_ != null) { - return metadataBuilder_.getMessageOrBuilder(); - } else { - return metadata_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - } - /** - *
-     * A flexible key-value map for passing additional context or parameters.
-     * 
- * - * .google.protobuf.Struct metadata = 3; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetMetadataFieldBuilder() { - if (metadataBuilder_ == null) { - metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getMetadata(), - getParentForChildren(), - isClean()); - metadata_ = null; - } - return metadataBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageRequest) - private static final io.a2a.grpc.SendMessageRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageRequest(); - } - - public static io.a2a.grpc.SendMessageRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public SendMessageRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java deleted file mode 100644 index de2e6cc12..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageRequestOrBuilder.java +++ /dev/null @@ -1,113 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface SendMessageRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The message to send to the agent.
-   * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the message field is set. - */ - boolean hasMessage(); - /** - *
-   * The message to send to the agent.
-   * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The message. - */ - io.a2a.grpc.Message getMessage(); - /** - *
-   * The message to send to the agent.
-   * 
- * - * .a2a.v1.Message message = 1 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); - - /** - *
-   * Configuration for the send request.
-   * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - * @return Whether the configuration field is set. - */ - boolean hasConfiguration(); - /** - *
-   * Configuration for the send request.
-   * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - * @return The configuration. - */ - io.a2a.grpc.SendMessageConfiguration getConfiguration(); - /** - *
-   * Configuration for the send request.
-   * 
- * - * .a2a.v1.SendMessageConfiguration configuration = 2; - */ - io.a2a.grpc.SendMessageConfigurationOrBuilder getConfigurationOrBuilder(); - - /** - *
-   * A flexible key-value map for passing additional context or parameters.
-   * 
- * - * .google.protobuf.Struct metadata = 3; - * @return Whether the metadata field is set. - */ - boolean hasMetadata(); - /** - *
-   * A flexible key-value map for passing additional context or parameters.
-   * 
- * - * .google.protobuf.Struct metadata = 3; - * @return The metadata. - */ - com.google.protobuf.Struct getMetadata(); - /** - *
-   * A flexible key-value map for passing additional context or parameters.
-   * 
- * - * .google.protobuf.Struct metadata = 3; - */ - com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java deleted file mode 100644 index 466f2206a..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponse.java +++ /dev/null @@ -1,867 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * ////// Response Messages ///////////
- * --8<-- [start:SendMessageResponse]
- * 
- * - * Protobuf type {@code a2a.v1.SendMessageResponse} - */ -@com.google.protobuf.Generated -public final class SendMessageResponse extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SendMessageResponse) - SendMessageResponseOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "SendMessageResponse"); - } - // Use SendMessageResponse.newBuilder() to construct. - private SendMessageResponse(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private SendMessageResponse() { - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SendMessageResponse.class, io.a2a.grpc.SendMessageResponse.Builder.class); - } - - private int payloadCase_ = 0; - @SuppressWarnings("serial") - private java.lang.Object payload_; - public enum PayloadCase - implements com.google.protobuf.Internal.EnumLite, - com.google.protobuf.AbstractMessage.InternalOneOfEnum { - TASK(1), - MESSAGE(2), - PAYLOAD_NOT_SET(0); - private final int value; - private PayloadCase(int value) { - this.value = value; - } - /** - * @param value The number of the enum to look for. - * @return The enum associated with the given number. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static PayloadCase valueOf(int value) { - return forNumber(value); - } - - public static PayloadCase forNumber(int value) { - switch (value) { - case 1: return TASK; - case 2: return MESSAGE; - case 0: return PAYLOAD_NOT_SET; - default: return null; - } - } - public int getNumber() { - return this.value; - } - }; - - public PayloadCase - getPayloadCase() { - return PayloadCase.forNumber( - payloadCase_); - } - - public static final int TASK_FIELD_NUMBER = 1; - /** - * .a2a.v1.Task task = 1; - * @return Whether the task field is set. - */ - @java.lang.Override - public boolean hasTask() { - return payloadCase_ == 1; - } - /** - * .a2a.v1.Task task = 1; - * @return The task. - */ - @java.lang.Override - public io.a2a.grpc.Task getTask() { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - /** - * .a2a.v1.Task task = 1; - */ - @java.lang.Override - public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - - public static final int MESSAGE_FIELD_NUMBER = 2; - /** - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - @java.lang.Override - public boolean hasMessage() { - return payloadCase_ == 2; - } - /** - * .a2a.v1.Message message = 2; - * @return The message. - */ - @java.lang.Override - public io.a2a.grpc.Message getMessage() { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - /** - * .a2a.v1.Message message = 2; - */ - @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (payloadCase_ == 1) { - output.writeMessage(1, (io.a2a.grpc.Task) payload_); - } - if (payloadCase_ == 2) { - output.writeMessage(2, (io.a2a.grpc.Message) payload_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (payloadCase_ == 1) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, (io.a2a.grpc.Task) payload_); - } - if (payloadCase_ == 2) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, (io.a2a.grpc.Message) payload_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.SendMessageResponse)) { - return super.equals(obj); - } - io.a2a.grpc.SendMessageResponse other = (io.a2a.grpc.SendMessageResponse) obj; - - if (!getPayloadCase().equals(other.getPayloadCase())) return false; - switch (payloadCase_) { - case 1: - if (!getTask() - .equals(other.getTask())) return false; - break; - case 2: - if (!getMessage() - .equals(other.getMessage())) return false; - break; - case 0: - default: - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - switch (payloadCase_) { - case 1: - hash = (37 * hash) + TASK_FIELD_NUMBER; - hash = (53 * hash) + getTask().hashCode(); - break; - case 2: - hash = (37 * hash) + MESSAGE_FIELD_NUMBER; - hash = (53 * hash) + getMessage().hashCode(); - break; - case 0: - default: - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.SendMessageResponse parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageResponse parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageResponse parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageResponse parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageResponse parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SendMessageResponse parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SendMessageResponse parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SendMessageResponse parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.SendMessageResponse parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.SendMessageResponse parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.SendMessageResponse parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SendMessageResponse parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.SendMessageResponse prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * ////// Response Messages ///////////
-   * --8<-- [start:SendMessageResponse]
-   * 
- * - * Protobuf type {@code a2a.v1.SendMessageResponse} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SendMessageResponse) - io.a2a.grpc.SendMessageResponseOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SendMessageResponse.class, io.a2a.grpc.SendMessageResponse.Builder.class); - } - - // Construct using io.a2a.grpc.SendMessageResponse.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - if (taskBuilder_ != null) { - taskBuilder_.clear(); - } - if (messageBuilder_ != null) { - messageBuilder_.clear(); - } - payloadCase_ = 0; - payload_ = null; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SendMessageResponse_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageResponse getDefaultInstanceForType() { - return io.a2a.grpc.SendMessageResponse.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.SendMessageResponse build() { - io.a2a.grpc.SendMessageResponse result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageResponse buildPartial() { - io.a2a.grpc.SendMessageResponse result = new io.a2a.grpc.SendMessageResponse(this); - if (bitField0_ != 0) { buildPartial0(result); } - buildPartialOneofs(result); - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.SendMessageResponse result) { - int from_bitField0_ = bitField0_; - } - - private void buildPartialOneofs(io.a2a.grpc.SendMessageResponse result) { - result.payloadCase_ = payloadCase_; - result.payload_ = this.payload_; - if (payloadCase_ == 1 && - taskBuilder_ != null) { - result.payload_ = taskBuilder_.build(); - } - if (payloadCase_ == 2 && - messageBuilder_ != null) { - result.payload_ = messageBuilder_.build(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.SendMessageResponse) { - return mergeFrom((io.a2a.grpc.SendMessageResponse)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.SendMessageResponse other) { - if (other == io.a2a.grpc.SendMessageResponse.getDefaultInstance()) return this; - switch (other.getPayloadCase()) { - case TASK: { - mergeTask(other.getTask()); - break; - } - case MESSAGE: { - mergeMessage(other.getMessage()); - break; - } - case PAYLOAD_NOT_SET: { - break; - } - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - input.readMessage( - internalGetTaskFieldBuilder().getBuilder(), - extensionRegistry); - payloadCase_ = 1; - break; - } // case 10 - case 18: { - input.readMessage( - internalGetMessageFieldBuilder().getBuilder(), - extensionRegistry); - payloadCase_ = 2; - break; - } // case 18 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int payloadCase_ = 0; - private java.lang.Object payload_; - public PayloadCase - getPayloadCase() { - return PayloadCase.forNumber( - payloadCase_); - } - - public Builder clearPayload() { - payloadCase_ = 0; - payload_ = null; - onChanged(); - return this; - } - - private int bitField0_; - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> taskBuilder_; - /** - * .a2a.v1.Task task = 1; - * @return Whether the task field is set. - */ - @java.lang.Override - public boolean hasTask() { - return payloadCase_ == 1; - } - /** - * .a2a.v1.Task task = 1; - * @return The task. - */ - @java.lang.Override - public io.a2a.grpc.Task getTask() { - if (taskBuilder_ == null) { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } else { - if (payloadCase_ == 1) { - return taskBuilder_.getMessage(); - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - } - /** - * .a2a.v1.Task task = 1; - */ - public Builder setTask(io.a2a.grpc.Task value) { - if (taskBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - payload_ = value; - onChanged(); - } else { - taskBuilder_.setMessage(value); - } - payloadCase_ = 1; - return this; - } - /** - * .a2a.v1.Task task = 1; - */ - public Builder setTask( - io.a2a.grpc.Task.Builder builderForValue) { - if (taskBuilder_ == null) { - payload_ = builderForValue.build(); - onChanged(); - } else { - taskBuilder_.setMessage(builderForValue.build()); - } - payloadCase_ = 1; - return this; - } - /** - * .a2a.v1.Task task = 1; - */ - public Builder mergeTask(io.a2a.grpc.Task value) { - if (taskBuilder_ == null) { - if (payloadCase_ == 1 && - payload_ != io.a2a.grpc.Task.getDefaultInstance()) { - payload_ = io.a2a.grpc.Task.newBuilder((io.a2a.grpc.Task) payload_) - .mergeFrom(value).buildPartial(); - } else { - payload_ = value; - } - onChanged(); - } else { - if (payloadCase_ == 1) { - taskBuilder_.mergeFrom(value); - } else { - taskBuilder_.setMessage(value); - } - } - payloadCase_ = 1; - return this; - } - /** - * .a2a.v1.Task task = 1; - */ - public Builder clearTask() { - if (taskBuilder_ == null) { - if (payloadCase_ == 1) { - payloadCase_ = 0; - payload_ = null; - onChanged(); - } - } else { - if (payloadCase_ == 1) { - payloadCase_ = 0; - payload_ = null; - } - taskBuilder_.clear(); - } - return this; - } - /** - * .a2a.v1.Task task = 1; - */ - public io.a2a.grpc.Task.Builder getTaskBuilder() { - return internalGetTaskFieldBuilder().getBuilder(); - } - /** - * .a2a.v1.Task task = 1; - */ - @java.lang.Override - public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { - if ((payloadCase_ == 1) && (taskBuilder_ != null)) { - return taskBuilder_.getMessageOrBuilder(); - } else { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - } - /** - * .a2a.v1.Task task = 1; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> - internalGetTaskFieldBuilder() { - if (taskBuilder_ == null) { - if (!(payloadCase_ == 1)) { - payload_ = io.a2a.grpc.Task.getDefaultInstance(); - } - taskBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder>( - (io.a2a.grpc.Task) payload_, - getParentForChildren(), - isClean()); - payload_ = null; - } - payloadCase_ = 1; - onChanged(); - return taskBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_; - /** - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - @java.lang.Override - public boolean hasMessage() { - return payloadCase_ == 2; - } - /** - * .a2a.v1.Message message = 2; - * @return The message. - */ - @java.lang.Override - public io.a2a.grpc.Message getMessage() { - if (messageBuilder_ == null) { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } else { - if (payloadCase_ == 2) { - return messageBuilder_.getMessage(); - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - } - /** - * .a2a.v1.Message message = 2; - */ - public Builder setMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - payload_ = value; - onChanged(); - } else { - messageBuilder_.setMessage(value); - } - payloadCase_ = 2; - return this; - } - /** - * .a2a.v1.Message message = 2; - */ - public Builder setMessage( - io.a2a.grpc.Message.Builder builderForValue) { - if (messageBuilder_ == null) { - payload_ = builderForValue.build(); - onChanged(); - } else { - messageBuilder_.setMessage(builderForValue.build()); - } - payloadCase_ = 2; - return this; - } - /** - * .a2a.v1.Message message = 2; - */ - public Builder mergeMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (payloadCase_ == 2 && - payload_ != io.a2a.grpc.Message.getDefaultInstance()) { - payload_ = io.a2a.grpc.Message.newBuilder((io.a2a.grpc.Message) payload_) - .mergeFrom(value).buildPartial(); - } else { - payload_ = value; - } - onChanged(); - } else { - if (payloadCase_ == 2) { - messageBuilder_.mergeFrom(value); - } else { - messageBuilder_.setMessage(value); - } - } - payloadCase_ = 2; - return this; - } - /** - * .a2a.v1.Message message = 2; - */ - public Builder clearMessage() { - if (messageBuilder_ == null) { - if (payloadCase_ == 2) { - payloadCase_ = 0; - payload_ = null; - onChanged(); - } - } else { - if (payloadCase_ == 2) { - payloadCase_ = 0; - payload_ = null; - } - messageBuilder_.clear(); - } - return this; - } - /** - * .a2a.v1.Message message = 2; - */ - public io.a2a.grpc.Message.Builder getMessageBuilder() { - return internalGetMessageFieldBuilder().getBuilder(); - } - /** - * .a2a.v1.Message message = 2; - */ - @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - if ((payloadCase_ == 2) && (messageBuilder_ != null)) { - return messageBuilder_.getMessageOrBuilder(); - } else { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - } - /** - * .a2a.v1.Message message = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> - internalGetMessageFieldBuilder() { - if (messageBuilder_ == null) { - if (!(payloadCase_ == 2)) { - payload_ = io.a2a.grpc.Message.getDefaultInstance(); - } - messageBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>( - (io.a2a.grpc.Message) payload_, - getParentForChildren(), - isClean()); - payload_ = null; - } - payloadCase_ = 2; - onChanged(); - return messageBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.SendMessageResponse) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.SendMessageResponse) - private static final io.a2a.grpc.SendMessageResponse DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.SendMessageResponse(); - } - - public static io.a2a.grpc.SendMessageResponse getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public SendMessageResponse parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.SendMessageResponse getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java deleted file mode 100644 index 355131b71..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SendMessageResponseOrBuilder.java +++ /dev/null @@ -1,44 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface SendMessageResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SendMessageResponse) - com.google.protobuf.MessageOrBuilder { - - /** - * .a2a.v1.Task task = 1; - * @return Whether the task field is set. - */ - boolean hasTask(); - /** - * .a2a.v1.Task task = 1; - * @return The task. - */ - io.a2a.grpc.Task getTask(); - /** - * .a2a.v1.Task task = 1; - */ - io.a2a.grpc.TaskOrBuilder getTaskOrBuilder(); - - /** - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - boolean hasMessage(); - /** - * .a2a.v1.Message message = 2; - * @return The message. - */ - io.a2a.grpc.Message getMessage(); - /** - * .a2a.v1.Message message = 2; - */ - io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); - - io.a2a.grpc.SendMessageResponse.PayloadCase getPayloadCase(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java deleted file mode 100644 index 3d27db5ef..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponse.java +++ /dev/null @@ -1,1475 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:StreamResponse]
- * A wrapper object used in streaming operations to encapsulate different types of response data.
- * 
- * - * Protobuf type {@code a2a.v1.StreamResponse} - */ -@com.google.protobuf.Generated -public final class StreamResponse extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.StreamResponse) - StreamResponseOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "StreamResponse"); - } - // Use StreamResponse.newBuilder() to construct. - private StreamResponse(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private StreamResponse() { - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.StreamResponse.class, io.a2a.grpc.StreamResponse.Builder.class); - } - - private int payloadCase_ = 0; - @SuppressWarnings("serial") - private java.lang.Object payload_; - public enum PayloadCase - implements com.google.protobuf.Internal.EnumLite, - com.google.protobuf.AbstractMessage.InternalOneOfEnum { - TASK(1), - MESSAGE(2), - STATUS_UPDATE(3), - ARTIFACT_UPDATE(4), - PAYLOAD_NOT_SET(0); - private final int value; - private PayloadCase(int value) { - this.value = value; - } - /** - * @param value The number of the enum to look for. - * @return The enum associated with the given number. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static PayloadCase valueOf(int value) { - return forNumber(value); - } - - public static PayloadCase forNumber(int value) { - switch (value) { - case 1: return TASK; - case 2: return MESSAGE; - case 3: return STATUS_UPDATE; - case 4: return ARTIFACT_UPDATE; - case 0: return PAYLOAD_NOT_SET; - default: return null; - } - } - public int getNumber() { - return this.value; - } - }; - - public PayloadCase - getPayloadCase() { - return PayloadCase.forNumber( - payloadCase_); - } - - public static final int TASK_FIELD_NUMBER = 1; - /** - *
-   * A Task object containing the current state of the task.
-   * 
- * - * .a2a.v1.Task task = 1; - * @return Whether the task field is set. - */ - @java.lang.Override - public boolean hasTask() { - return payloadCase_ == 1; - } - /** - *
-   * A Task object containing the current state of the task.
-   * 
- * - * .a2a.v1.Task task = 1; - * @return The task. - */ - @java.lang.Override - public io.a2a.grpc.Task getTask() { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - /** - *
-   * A Task object containing the current state of the task.
-   * 
- * - * .a2a.v1.Task task = 1; - */ - @java.lang.Override - public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - - public static final int MESSAGE_FIELD_NUMBER = 2; - /** - *
-   * A Message object containing a message from the agent.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - @java.lang.Override - public boolean hasMessage() { - return payloadCase_ == 2; - } - /** - *
-   * A Message object containing a message from the agent.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return The message. - */ - @java.lang.Override - public io.a2a.grpc.Message getMessage() { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - /** - *
-   * A Message object containing a message from the agent.
-   * 
- * - * .a2a.v1.Message message = 2; - */ - @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - - public static final int STATUS_UPDATE_FIELD_NUMBER = 3; - /** - *
-   * An event indicating a task status update.
-   * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - * @return Whether the statusUpdate field is set. - */ - @java.lang.Override - public boolean hasStatusUpdate() { - return payloadCase_ == 3; - } - /** - *
-   * An event indicating a task status update.
-   * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - * @return The statusUpdate. - */ - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() { - if (payloadCase_ == 3) { - return (io.a2a.grpc.TaskStatusUpdateEvent) payload_; - } - return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance(); - } - /** - *
-   * An event indicating a task status update.
-   * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { - if (payloadCase_ == 3) { - return (io.a2a.grpc.TaskStatusUpdateEvent) payload_; - } - return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance(); - } - - public static final int ARTIFACT_UPDATE_FIELD_NUMBER = 4; - /** - *
-   * An event indicating a task artifact update.
-   * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - * @return Whether the artifactUpdate field is set. - */ - @java.lang.Override - public boolean hasArtifactUpdate() { - return payloadCase_ == 4; - } - /** - *
-   * An event indicating a task artifact update.
-   * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - * @return The artifactUpdate. - */ - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() { - if (payloadCase_ == 4) { - return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_; - } - return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); - } - /** - *
-   * An event indicating a task artifact update.
-   * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() { - if (payloadCase_ == 4) { - return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_; - } - return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (payloadCase_ == 1) { - output.writeMessage(1, (io.a2a.grpc.Task) payload_); - } - if (payloadCase_ == 2) { - output.writeMessage(2, (io.a2a.grpc.Message) payload_); - } - if (payloadCase_ == 3) { - output.writeMessage(3, (io.a2a.grpc.TaskStatusUpdateEvent) payload_); - } - if (payloadCase_ == 4) { - output.writeMessage(4, (io.a2a.grpc.TaskArtifactUpdateEvent) payload_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (payloadCase_ == 1) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, (io.a2a.grpc.Task) payload_); - } - if (payloadCase_ == 2) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, (io.a2a.grpc.Message) payload_); - } - if (payloadCase_ == 3) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, (io.a2a.grpc.TaskStatusUpdateEvent) payload_); - } - if (payloadCase_ == 4) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, (io.a2a.grpc.TaskArtifactUpdateEvent) payload_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.StreamResponse)) { - return super.equals(obj); - } - io.a2a.grpc.StreamResponse other = (io.a2a.grpc.StreamResponse) obj; - - if (!getPayloadCase().equals(other.getPayloadCase())) return false; - switch (payloadCase_) { - case 1: - if (!getTask() - .equals(other.getTask())) return false; - break; - case 2: - if (!getMessage() - .equals(other.getMessage())) return false; - break; - case 3: - if (!getStatusUpdate() - .equals(other.getStatusUpdate())) return false; - break; - case 4: - if (!getArtifactUpdate() - .equals(other.getArtifactUpdate())) return false; - break; - case 0: - default: - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - switch (payloadCase_) { - case 1: - hash = (37 * hash) + TASK_FIELD_NUMBER; - hash = (53 * hash) + getTask().hashCode(); - break; - case 2: - hash = (37 * hash) + MESSAGE_FIELD_NUMBER; - hash = (53 * hash) + getMessage().hashCode(); - break; - case 3: - hash = (37 * hash) + STATUS_UPDATE_FIELD_NUMBER; - hash = (53 * hash) + getStatusUpdate().hashCode(); - break; - case 4: - hash = (37 * hash) + ARTIFACT_UPDATE_FIELD_NUMBER; - hash = (53 * hash) + getArtifactUpdate().hashCode(); - break; - case 0: - default: - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.StreamResponse parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.StreamResponse parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.StreamResponse parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.StreamResponse parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.StreamResponse parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.StreamResponse parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.StreamResponse parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.StreamResponse parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.StreamResponse parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.StreamResponse parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.StreamResponse parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.StreamResponse parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.StreamResponse prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:StreamResponse]
-   * A wrapper object used in streaming operations to encapsulate different types of response data.
-   * 
- * - * Protobuf type {@code a2a.v1.StreamResponse} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.StreamResponse) - io.a2a.grpc.StreamResponseOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.StreamResponse.class, io.a2a.grpc.StreamResponse.Builder.class); - } - - // Construct using io.a2a.grpc.StreamResponse.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - if (taskBuilder_ != null) { - taskBuilder_.clear(); - } - if (messageBuilder_ != null) { - messageBuilder_.clear(); - } - if (statusUpdateBuilder_ != null) { - statusUpdateBuilder_.clear(); - } - if (artifactUpdateBuilder_ != null) { - artifactUpdateBuilder_.clear(); - } - payloadCase_ = 0; - payload_ = null; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StreamResponse_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.StreamResponse getDefaultInstanceForType() { - return io.a2a.grpc.StreamResponse.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.StreamResponse build() { - io.a2a.grpc.StreamResponse result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.StreamResponse buildPartial() { - io.a2a.grpc.StreamResponse result = new io.a2a.grpc.StreamResponse(this); - if (bitField0_ != 0) { buildPartial0(result); } - buildPartialOneofs(result); - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.StreamResponse result) { - int from_bitField0_ = bitField0_; - } - - private void buildPartialOneofs(io.a2a.grpc.StreamResponse result) { - result.payloadCase_ = payloadCase_; - result.payload_ = this.payload_; - if (payloadCase_ == 1 && - taskBuilder_ != null) { - result.payload_ = taskBuilder_.build(); - } - if (payloadCase_ == 2 && - messageBuilder_ != null) { - result.payload_ = messageBuilder_.build(); - } - if (payloadCase_ == 3 && - statusUpdateBuilder_ != null) { - result.payload_ = statusUpdateBuilder_.build(); - } - if (payloadCase_ == 4 && - artifactUpdateBuilder_ != null) { - result.payload_ = artifactUpdateBuilder_.build(); - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.StreamResponse) { - return mergeFrom((io.a2a.grpc.StreamResponse)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.StreamResponse other) { - if (other == io.a2a.grpc.StreamResponse.getDefaultInstance()) return this; - switch (other.getPayloadCase()) { - case TASK: { - mergeTask(other.getTask()); - break; - } - case MESSAGE: { - mergeMessage(other.getMessage()); - break; - } - case STATUS_UPDATE: { - mergeStatusUpdate(other.getStatusUpdate()); - break; - } - case ARTIFACT_UPDATE: { - mergeArtifactUpdate(other.getArtifactUpdate()); - break; - } - case PAYLOAD_NOT_SET: { - break; - } - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - input.readMessage( - internalGetTaskFieldBuilder().getBuilder(), - extensionRegistry); - payloadCase_ = 1; - break; - } // case 10 - case 18: { - input.readMessage( - internalGetMessageFieldBuilder().getBuilder(), - extensionRegistry); - payloadCase_ = 2; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetStatusUpdateFieldBuilder().getBuilder(), - extensionRegistry); - payloadCase_ = 3; - break; - } // case 26 - case 34: { - input.readMessage( - internalGetArtifactUpdateFieldBuilder().getBuilder(), - extensionRegistry); - payloadCase_ = 4; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int payloadCase_ = 0; - private java.lang.Object payload_; - public PayloadCase - getPayloadCase() { - return PayloadCase.forNumber( - payloadCase_); - } - - public Builder clearPayload() { - payloadCase_ = 0; - payload_ = null; - onChanged(); - return this; - } - - private int bitField0_; - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> taskBuilder_; - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - * @return Whether the task field is set. - */ - @java.lang.Override - public boolean hasTask() { - return payloadCase_ == 1; - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - * @return The task. - */ - @java.lang.Override - public io.a2a.grpc.Task getTask() { - if (taskBuilder_ == null) { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } else { - if (payloadCase_ == 1) { - return taskBuilder_.getMessage(); - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - */ - public Builder setTask(io.a2a.grpc.Task value) { - if (taskBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - payload_ = value; - onChanged(); - } else { - taskBuilder_.setMessage(value); - } - payloadCase_ = 1; - return this; - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - */ - public Builder setTask( - io.a2a.grpc.Task.Builder builderForValue) { - if (taskBuilder_ == null) { - payload_ = builderForValue.build(); - onChanged(); - } else { - taskBuilder_.setMessage(builderForValue.build()); - } - payloadCase_ = 1; - return this; - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - */ - public Builder mergeTask(io.a2a.grpc.Task value) { - if (taskBuilder_ == null) { - if (payloadCase_ == 1 && - payload_ != io.a2a.grpc.Task.getDefaultInstance()) { - payload_ = io.a2a.grpc.Task.newBuilder((io.a2a.grpc.Task) payload_) - .mergeFrom(value).buildPartial(); - } else { - payload_ = value; - } - onChanged(); - } else { - if (payloadCase_ == 1) { - taskBuilder_.mergeFrom(value); - } else { - taskBuilder_.setMessage(value); - } - } - payloadCase_ = 1; - return this; - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - */ - public Builder clearTask() { - if (taskBuilder_ == null) { - if (payloadCase_ == 1) { - payloadCase_ = 0; - payload_ = null; - onChanged(); - } - } else { - if (payloadCase_ == 1) { - payloadCase_ = 0; - payload_ = null; - } - taskBuilder_.clear(); - } - return this; - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - */ - public io.a2a.grpc.Task.Builder getTaskBuilder() { - return internalGetTaskFieldBuilder().getBuilder(); - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - */ - @java.lang.Override - public io.a2a.grpc.TaskOrBuilder getTaskOrBuilder() { - if ((payloadCase_ == 1) && (taskBuilder_ != null)) { - return taskBuilder_.getMessageOrBuilder(); - } else { - if (payloadCase_ == 1) { - return (io.a2a.grpc.Task) payload_; - } - return io.a2a.grpc.Task.getDefaultInstance(); - } - } - /** - *
-     * A Task object containing the current state of the task.
-     * 
- * - * .a2a.v1.Task task = 1; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder> - internalGetTaskFieldBuilder() { - if (taskBuilder_ == null) { - if (!(payloadCase_ == 1)) { - payload_ = io.a2a.grpc.Task.getDefaultInstance(); - } - taskBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Task, io.a2a.grpc.Task.Builder, io.a2a.grpc.TaskOrBuilder>( - (io.a2a.grpc.Task) payload_, - getParentForChildren(), - isClean()); - payload_ = null; - } - payloadCase_ = 1; - onChanged(); - return taskBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_; - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - @java.lang.Override - public boolean hasMessage() { - return payloadCase_ == 2; - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - * @return The message. - */ - @java.lang.Override - public io.a2a.grpc.Message getMessage() { - if (messageBuilder_ == null) { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } else { - if (payloadCase_ == 2) { - return messageBuilder_.getMessage(); - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder setMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - payload_ = value; - onChanged(); - } else { - messageBuilder_.setMessage(value); - } - payloadCase_ = 2; - return this; - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder setMessage( - io.a2a.grpc.Message.Builder builderForValue) { - if (messageBuilder_ == null) { - payload_ = builderForValue.build(); - onChanged(); - } else { - messageBuilder_.setMessage(builderForValue.build()); - } - payloadCase_ = 2; - return this; - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder mergeMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (payloadCase_ == 2 && - payload_ != io.a2a.grpc.Message.getDefaultInstance()) { - payload_ = io.a2a.grpc.Message.newBuilder((io.a2a.grpc.Message) payload_) - .mergeFrom(value).buildPartial(); - } else { - payload_ = value; - } - onChanged(); - } else { - if (payloadCase_ == 2) { - messageBuilder_.mergeFrom(value); - } else { - messageBuilder_.setMessage(value); - } - } - payloadCase_ = 2; - return this; - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder clearMessage() { - if (messageBuilder_ == null) { - if (payloadCase_ == 2) { - payloadCase_ = 0; - payload_ = null; - onChanged(); - } - } else { - if (payloadCase_ == 2) { - payloadCase_ = 0; - payload_ = null; - } - messageBuilder_.clear(); - } - return this; - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public io.a2a.grpc.Message.Builder getMessageBuilder() { - return internalGetMessageFieldBuilder().getBuilder(); - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - if ((payloadCase_ == 2) && (messageBuilder_ != null)) { - return messageBuilder_.getMessageOrBuilder(); - } else { - if (payloadCase_ == 2) { - return (io.a2a.grpc.Message) payload_; - } - return io.a2a.grpc.Message.getDefaultInstance(); - } - } - /** - *
-     * A Message object containing a message from the agent.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> - internalGetMessageFieldBuilder() { - if (messageBuilder_ == null) { - if (!(payloadCase_ == 2)) { - payload_ = io.a2a.grpc.Message.getDefaultInstance(); - } - messageBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>( - (io.a2a.grpc.Message) payload_, - getParentForChildren(), - isClean()); - payload_ = null; - } - payloadCase_ = 2; - onChanged(); - return messageBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatusUpdateEvent, io.a2a.grpc.TaskStatusUpdateEvent.Builder, io.a2a.grpc.TaskStatusUpdateEventOrBuilder> statusUpdateBuilder_; - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - * @return Whether the statusUpdate field is set. - */ - @java.lang.Override - public boolean hasStatusUpdate() { - return payloadCase_ == 3; - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - * @return The statusUpdate. - */ - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate() { - if (statusUpdateBuilder_ == null) { - if (payloadCase_ == 3) { - return (io.a2a.grpc.TaskStatusUpdateEvent) payload_; - } - return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance(); - } else { - if (payloadCase_ == 3) { - return statusUpdateBuilder_.getMessage(); - } - return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance(); - } - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - public Builder setStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) { - if (statusUpdateBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - payload_ = value; - onChanged(); - } else { - statusUpdateBuilder_.setMessage(value); - } - payloadCase_ = 3; - return this; - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - public Builder setStatusUpdate( - io.a2a.grpc.TaskStatusUpdateEvent.Builder builderForValue) { - if (statusUpdateBuilder_ == null) { - payload_ = builderForValue.build(); - onChanged(); - } else { - statusUpdateBuilder_.setMessage(builderForValue.build()); - } - payloadCase_ = 3; - return this; - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - public Builder mergeStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent value) { - if (statusUpdateBuilder_ == null) { - if (payloadCase_ == 3 && - payload_ != io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance()) { - payload_ = io.a2a.grpc.TaskStatusUpdateEvent.newBuilder((io.a2a.grpc.TaskStatusUpdateEvent) payload_) - .mergeFrom(value).buildPartial(); - } else { - payload_ = value; - } - onChanged(); - } else { - if (payloadCase_ == 3) { - statusUpdateBuilder_.mergeFrom(value); - } else { - statusUpdateBuilder_.setMessage(value); - } - } - payloadCase_ = 3; - return this; - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - public Builder clearStatusUpdate() { - if (statusUpdateBuilder_ == null) { - if (payloadCase_ == 3) { - payloadCase_ = 0; - payload_ = null; - onChanged(); - } - } else { - if (payloadCase_ == 3) { - payloadCase_ = 0; - payload_ = null; - } - statusUpdateBuilder_.clear(); - } - return this; - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - public io.a2a.grpc.TaskStatusUpdateEvent.Builder getStatusUpdateBuilder() { - return internalGetStatusUpdateFieldBuilder().getBuilder(); - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder() { - if ((payloadCase_ == 3) && (statusUpdateBuilder_ != null)) { - return statusUpdateBuilder_.getMessageOrBuilder(); - } else { - if (payloadCase_ == 3) { - return (io.a2a.grpc.TaskStatusUpdateEvent) payload_; - } - return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance(); - } - } - /** - *
-     * An event indicating a task status update.
-     * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatusUpdateEvent, io.a2a.grpc.TaskStatusUpdateEvent.Builder, io.a2a.grpc.TaskStatusUpdateEventOrBuilder> - internalGetStatusUpdateFieldBuilder() { - if (statusUpdateBuilder_ == null) { - if (!(payloadCase_ == 3)) { - payload_ = io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance(); - } - statusUpdateBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatusUpdateEvent, io.a2a.grpc.TaskStatusUpdateEvent.Builder, io.a2a.grpc.TaskStatusUpdateEventOrBuilder>( - (io.a2a.grpc.TaskStatusUpdateEvent) payload_, - getParentForChildren(), - isClean()); - payload_ = null; - } - payloadCase_ = 3; - onChanged(); - return statusUpdateBuilder_; - } - - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskArtifactUpdateEvent, io.a2a.grpc.TaskArtifactUpdateEvent.Builder, io.a2a.grpc.TaskArtifactUpdateEventOrBuilder> artifactUpdateBuilder_; - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - * @return Whether the artifactUpdate field is set. - */ - @java.lang.Override - public boolean hasArtifactUpdate() { - return payloadCase_ == 4; - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - * @return The artifactUpdate. - */ - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate() { - if (artifactUpdateBuilder_ == null) { - if (payloadCase_ == 4) { - return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_; - } - return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); - } else { - if (payloadCase_ == 4) { - return artifactUpdateBuilder_.getMessage(); - } - return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); - } - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - public Builder setArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) { - if (artifactUpdateBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - payload_ = value; - onChanged(); - } else { - artifactUpdateBuilder_.setMessage(value); - } - payloadCase_ = 4; - return this; - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - public Builder setArtifactUpdate( - io.a2a.grpc.TaskArtifactUpdateEvent.Builder builderForValue) { - if (artifactUpdateBuilder_ == null) { - payload_ = builderForValue.build(); - onChanged(); - } else { - artifactUpdateBuilder_.setMessage(builderForValue.build()); - } - payloadCase_ = 4; - return this; - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - public Builder mergeArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent value) { - if (artifactUpdateBuilder_ == null) { - if (payloadCase_ == 4 && - payload_ != io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) { - payload_ = io.a2a.grpc.TaskArtifactUpdateEvent.newBuilder((io.a2a.grpc.TaskArtifactUpdateEvent) payload_) - .mergeFrom(value).buildPartial(); - } else { - payload_ = value; - } - onChanged(); - } else { - if (payloadCase_ == 4) { - artifactUpdateBuilder_.mergeFrom(value); - } else { - artifactUpdateBuilder_.setMessage(value); - } - } - payloadCase_ = 4; - return this; - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - public Builder clearArtifactUpdate() { - if (artifactUpdateBuilder_ == null) { - if (payloadCase_ == 4) { - payloadCase_ = 0; - payload_ = null; - onChanged(); - } - } else { - if (payloadCase_ == 4) { - payloadCase_ = 0; - payload_ = null; - } - artifactUpdateBuilder_.clear(); - } - return this; - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - public io.a2a.grpc.TaskArtifactUpdateEvent.Builder getArtifactUpdateBuilder() { - return internalGetArtifactUpdateFieldBuilder().getBuilder(); - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder() { - if ((payloadCase_ == 4) && (artifactUpdateBuilder_ != null)) { - return artifactUpdateBuilder_.getMessageOrBuilder(); - } else { - if (payloadCase_ == 4) { - return (io.a2a.grpc.TaskArtifactUpdateEvent) payload_; - } - return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); - } - } - /** - *
-     * An event indicating a task artifact update.
-     * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskArtifactUpdateEvent, io.a2a.grpc.TaskArtifactUpdateEvent.Builder, io.a2a.grpc.TaskArtifactUpdateEventOrBuilder> - internalGetArtifactUpdateFieldBuilder() { - if (artifactUpdateBuilder_ == null) { - if (!(payloadCase_ == 4)) { - payload_ = io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); - } - artifactUpdateBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskArtifactUpdateEvent, io.a2a.grpc.TaskArtifactUpdateEvent.Builder, io.a2a.grpc.TaskArtifactUpdateEventOrBuilder>( - (io.a2a.grpc.TaskArtifactUpdateEvent) payload_, - getParentForChildren(), - isClean()); - payload_ = null; - } - payloadCase_ = 4; - onChanged(); - return artifactUpdateBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.StreamResponse) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.StreamResponse) - private static final io.a2a.grpc.StreamResponse DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.StreamResponse(); - } - - public static io.a2a.grpc.StreamResponse getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public StreamResponse parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.StreamResponse getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java deleted file mode 100644 index 5688ed06b..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/StreamResponseOrBuilder.java +++ /dev/null @@ -1,122 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface StreamResponseOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.StreamResponse) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * A Task object containing the current state of the task.
-   * 
- * - * .a2a.v1.Task task = 1; - * @return Whether the task field is set. - */ - boolean hasTask(); - /** - *
-   * A Task object containing the current state of the task.
-   * 
- * - * .a2a.v1.Task task = 1; - * @return The task. - */ - io.a2a.grpc.Task getTask(); - /** - *
-   * A Task object containing the current state of the task.
-   * 
- * - * .a2a.v1.Task task = 1; - */ - io.a2a.grpc.TaskOrBuilder getTaskOrBuilder(); - - /** - *
-   * A Message object containing a message from the agent.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - boolean hasMessage(); - /** - *
-   * A Message object containing a message from the agent.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return The message. - */ - io.a2a.grpc.Message getMessage(); - /** - *
-   * A Message object containing a message from the agent.
-   * 
- * - * .a2a.v1.Message message = 2; - */ - io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); - - /** - *
-   * An event indicating a task status update.
-   * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - * @return Whether the statusUpdate field is set. - */ - boolean hasStatusUpdate(); - /** - *
-   * An event indicating a task status update.
-   * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - * @return The statusUpdate. - */ - io.a2a.grpc.TaskStatusUpdateEvent getStatusUpdate(); - /** - *
-   * An event indicating a task status update.
-   * 
- * - * .a2a.v1.TaskStatusUpdateEvent status_update = 3; - */ - io.a2a.grpc.TaskStatusUpdateEventOrBuilder getStatusUpdateOrBuilder(); - - /** - *
-   * An event indicating a task artifact update.
-   * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - * @return Whether the artifactUpdate field is set. - */ - boolean hasArtifactUpdate(); - /** - *
-   * An event indicating a task artifact update.
-   * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - * @return The artifactUpdate. - */ - io.a2a.grpc.TaskArtifactUpdateEvent getArtifactUpdate(); - /** - *
-   * An event indicating a task artifact update.
-   * 
- * - * .a2a.v1.TaskArtifactUpdateEvent artifact_update = 4; - */ - io.a2a.grpc.TaskArtifactUpdateEventOrBuilder getArtifactUpdateOrBuilder(); - - io.a2a.grpc.StreamResponse.PayloadCase getPayloadCase(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StringList.java b/spec-grpc/src/main/java/io/a2a/grpc/StringList.java deleted file mode 100644 index 6fed6e257..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/StringList.java +++ /dev/null @@ -1,563 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
- * 
- * - * Protobuf type {@code a2a.v1.StringList} - */ -@com.google.protobuf.Generated -public final class StringList extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.StringList) - StringListOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "StringList"); - } - // Use StringList.newBuilder() to construct. - private StringList(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private StringList() { - list_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.StringList.class, io.a2a.grpc.StringList.Builder.class); - } - - public static final int LIST_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private com.google.protobuf.LazyStringArrayList list_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - /** - * repeated string list = 1; - * @return A list containing the list. - */ - public com.google.protobuf.ProtocolStringList - getListList() { - return list_; - } - /** - * repeated string list = 1; - * @return The count of list. - */ - public int getListCount() { - return list_.size(); - } - /** - * repeated string list = 1; - * @param index The index of the element to return. - * @return The list at the given index. - */ - public java.lang.String getList(int index) { - return list_.get(index); - } - /** - * repeated string list = 1; - * @param index The index of the value to return. - * @return The bytes of the list at the given index. - */ - public com.google.protobuf.ByteString - getListBytes(int index) { - return list_.getByteString(index); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - for (int i = 0; i < list_.size(); i++) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, list_.getRaw(i)); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - { - int dataSize = 0; - for (int i = 0; i < list_.size(); i++) { - dataSize += computeStringSizeNoTag(list_.getRaw(i)); - } - size += dataSize; - size += 1 * getListList().size(); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.StringList)) { - return super.equals(obj); - } - io.a2a.grpc.StringList other = (io.a2a.grpc.StringList) obj; - - if (!getListList() - .equals(other.getListList())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (getListCount() > 0) { - hash = (37 * hash) + LIST_FIELD_NUMBER; - hash = (53 * hash) + getListList().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.StringList parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.StringList parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.StringList parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.StringList parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.StringList parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.StringList parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.StringList parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.StringList parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.StringList parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.StringList parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.StringList parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.StringList parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.StringList prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * 
- * - * Protobuf type {@code a2a.v1.StringList} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.StringList) - io.a2a.grpc.StringListOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.StringList.class, io.a2a.grpc.StringList.Builder.class); - } - - // Construct using io.a2a.grpc.StringList.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - list_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_StringList_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.StringList getDefaultInstanceForType() { - return io.a2a.grpc.StringList.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.StringList build() { - io.a2a.grpc.StringList result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.StringList buildPartial() { - io.a2a.grpc.StringList result = new io.a2a.grpc.StringList(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.StringList result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - list_.makeImmutable(); - result.list_ = list_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.StringList) { - return mergeFrom((io.a2a.grpc.StringList)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.StringList other) { - if (other == io.a2a.grpc.StringList.getDefaultInstance()) return this; - if (!other.list_.isEmpty()) { - if (list_.isEmpty()) { - list_ = other.list_; - bitField0_ |= 0x00000001; - } else { - ensureListIsMutable(); - list_.addAll(other.list_); - } - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - java.lang.String s = input.readStringRequireUtf8(); - ensureListIsMutable(); - list_.add(s); - break; - } // case 10 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private com.google.protobuf.LazyStringArrayList list_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - private void ensureListIsMutable() { - if (!list_.isModifiable()) { - list_ = new com.google.protobuf.LazyStringArrayList(list_); - } - bitField0_ |= 0x00000001; - } - /** - * repeated string list = 1; - * @return A list containing the list. - */ - public com.google.protobuf.ProtocolStringList - getListList() { - list_.makeImmutable(); - return list_; - } - /** - * repeated string list = 1; - * @return The count of list. - */ - public int getListCount() { - return list_.size(); - } - /** - * repeated string list = 1; - * @param index The index of the element to return. - * @return The list at the given index. - */ - public java.lang.String getList(int index) { - return list_.get(index); - } - /** - * repeated string list = 1; - * @param index The index of the value to return. - * @return The bytes of the list at the given index. - */ - public com.google.protobuf.ByteString - getListBytes(int index) { - return list_.getByteString(index); - } - /** - * repeated string list = 1; - * @param index The index to set the value at. - * @param value The list to set. - * @return This builder for chaining. - */ - public Builder setList( - int index, java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureListIsMutable(); - list_.set(index, value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - * repeated string list = 1; - * @param value The list to add. - * @return This builder for chaining. - */ - public Builder addList( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - ensureListIsMutable(); - list_.add(value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - * repeated string list = 1; - * @param values The list to add. - * @return This builder for chaining. - */ - public Builder addAllList( - java.lang.Iterable values) { - ensureListIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, list_); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - * repeated string list = 1; - * @return This builder for chaining. - */ - public Builder clearList() { - list_ = - com.google.protobuf.LazyStringArrayList.emptyList(); - bitField0_ = (bitField0_ & ~0x00000001);; - onChanged(); - return this; - } - /** - * repeated string list = 1; - * @param value The bytes of the list to add. - * @return This builder for chaining. - */ - public Builder addListBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - ensureListIsMutable(); - list_.add(value); - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.StringList) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.StringList) - private static final io.a2a.grpc.StringList DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.StringList(); - } - - public static io.a2a.grpc.StringList getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public StringList parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.StringList getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java deleted file mode 100644 index 48cdceac1..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/StringListOrBuilder.java +++ /dev/null @@ -1,37 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface StringListOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.StringList) - com.google.protobuf.MessageOrBuilder { - - /** - * repeated string list = 1; - * @return A list containing the list. - */ - java.util.List - getListList(); - /** - * repeated string list = 1; - * @return The count of list. - */ - int getListCount(); - /** - * repeated string list = 1; - * @param index The index of the element to return. - * @return The list at the given index. - */ - java.lang.String getList(int index); - /** - * repeated string list = 1; - * @param index The index of the value to return. - * @return The bytes of the list at the given index. - */ - com.google.protobuf.ByteString - getListBytes(int index); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java deleted file mode 100644 index 82a95620a..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequest.java +++ /dev/null @@ -1,702 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:SubscribeToTaskRequest]
- * 
- * - * Protobuf type {@code a2a.v1.SubscribeToTaskRequest} - */ -@com.google.protobuf.Generated -public final class SubscribeToTaskRequest extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.SubscribeToTaskRequest) - SubscribeToTaskRequestOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "SubscribeToTaskRequest"); - } - // Use SubscribeToTaskRequest.newBuilder() to construct. - private SubscribeToTaskRequest(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private SubscribeToTaskRequest() { - tenant_ = ""; - id_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SubscribeToTaskRequest.class, io.a2a.grpc.SubscribeToTaskRequest.Builder.class); - } - - public static final int TENANT_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * The resource id of the task to subscribe to.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * The resource id of the task to subscribe to.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.SubscribeToTaskRequest)) { - return super.equals(obj); - } - io.a2a.grpc.SubscribeToTaskRequest other = (io.a2a.grpc.SubscribeToTaskRequest) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getId() - .equals(other.getId())) return false; - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.SubscribeToTaskRequest parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.SubscribeToTaskRequest parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.SubscribeToTaskRequest parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.SubscribeToTaskRequest prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:SubscribeToTaskRequest]
-   * 
- * - * Protobuf type {@code a2a.v1.SubscribeToTaskRequest} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.SubscribeToTaskRequest) - io.a2a.grpc.SubscribeToTaskRequestOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.SubscribeToTaskRequest.class, io.a2a.grpc.SubscribeToTaskRequest.Builder.class); - } - - // Construct using io.a2a.grpc.SubscribeToTaskRequest.newBuilder() - private Builder() { - - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - id_ = ""; - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_SubscribeToTaskRequest_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.SubscribeToTaskRequest getDefaultInstanceForType() { - return io.a2a.grpc.SubscribeToTaskRequest.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.SubscribeToTaskRequest build() { - io.a2a.grpc.SubscribeToTaskRequest result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.SubscribeToTaskRequest buildPartial() { - io.a2a.grpc.SubscribeToTaskRequest result = new io.a2a.grpc.SubscribeToTaskRequest(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.SubscribeToTaskRequest result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.id_ = id_; - } - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.SubscribeToTaskRequest) { - return mergeFrom((io.a2a.grpc.SubscribeToTaskRequest)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.SubscribeToTaskRequest other) { - if (other == io.a2a.grpc.SubscribeToTaskRequest.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000002; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 18: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 18 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant, provided as a path parameter.
-     * 
- * - * string tenant = 2; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object id_ = ""; - /** - *
-     * The resource id of the task to subscribe to.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The resource id of the task to subscribe to.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The resource id of the task to subscribe to.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The resource id of the task to subscribe to.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The resource id of the task to subscribe to.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.SubscribeToTaskRequest) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.SubscribeToTaskRequest) - private static final io.a2a.grpc.SubscribeToTaskRequest DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.SubscribeToTaskRequest(); - } - - public static io.a2a.grpc.SubscribeToTaskRequest getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public SubscribeToTaskRequest parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.SubscribeToTaskRequest getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java deleted file mode 100644 index 39f287b30..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/SubscribeToTaskRequestOrBuilder.java +++ /dev/null @@ -1,52 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface SubscribeToTaskRequestOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.SubscribeToTaskRequest) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant, provided as a path parameter.
-   * 
- * - * string tenant = 2; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The resource id of the task to subscribe to.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * The resource id of the task to subscribe to.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/Task.java b/spec-grpc/src/main/java/io/a2a/grpc/Task.java deleted file mode 100644 index cc1e66690..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/Task.java +++ /dev/null @@ -1,2123 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:Task]
- * Task is the core unit of action for A2A. It has a current status
- * and when results are created for the task they are stored in the
- * artifact. If there are multiple turns for a task, these are stored in
- * history.
- * 
- * - * Protobuf type {@code a2a.v1.Task} - */ -@com.google.protobuf.Generated -public final class Task extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.Task) - TaskOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "Task"); - } - // Use Task.newBuilder() to construct. - private Task(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private Task() { - id_ = ""; - contextId_ = ""; - artifacts_ = java.util.Collections.emptyList(); - history_ = java.util.Collections.emptyList(); - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Task.class, io.a2a.grpc.Task.Builder.class); - } - - private int bitField0_; - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * Unique identifier (e.g. UUID) for the task, generated by the server for a
-   * new task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * Unique identifier (e.g. UUID) for the task, generated by the server for a
-   * new task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONTEXT_ID_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object contextId_ = ""; - /** - *
-   * Unique identifier (e.g. UUID) for the contextual collection of interactions
-   * (tasks and messages). Created by the A2A server.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - @java.lang.Override - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } - } - /** - *
-   * Unique identifier (e.g. UUID) for the contextual collection of interactions
-   * (tasks and messages). Created by the A2A server.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int STATUS_FIELD_NUMBER = 3; - private io.a2a.grpc.TaskStatus status_; - /** - *
-   * The current status of a Task, including state and a message.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the status field is set. - */ - @java.lang.Override - public boolean hasStatus() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The current status of a Task, including state and a message.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The status. - */ - @java.lang.Override - public io.a2a.grpc.TaskStatus getStatus() { - return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } - /** - *
-   * The current status of a Task, including state and a message.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { - return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } - - public static final int ARTIFACTS_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private java.util.List artifacts_; - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - @java.lang.Override - public java.util.List getArtifactsList() { - return artifacts_; - } - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - @java.lang.Override - public java.util.List - getArtifactsOrBuilderList() { - return artifacts_; - } - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - @java.lang.Override - public int getArtifactsCount() { - return artifacts_.size(); - } - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - @java.lang.Override - public io.a2a.grpc.Artifact getArtifacts(int index) { - return artifacts_.get(index); - } - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - @java.lang.Override - public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( - int index) { - return artifacts_.get(index); - } - - public static final int HISTORY_FIELD_NUMBER = 5; - @SuppressWarnings("serial") - private java.util.List history_; - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - @java.lang.Override - public java.util.List getHistoryList() { - return history_; - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - @java.lang.Override - public java.util.List - getHistoryOrBuilderList() { - return history_; - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - @java.lang.Override - public int getHistoryCount() { - return history_.size(); - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - @java.lang.Override - public io.a2a.grpc.Message getHistory(int index) { - return history_.get(index); - } - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( - int index) { - return history_.get(index); - } - - public static final int METADATA_FIELD_NUMBER = 6; - private com.google.protobuf.Struct metadata_; - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * A key/value object to store custom metadata about a task.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - @java.lang.Override - public boolean hasMetadata() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * A key/value object to store custom metadata about a task.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - @java.lang.Override - public com.google.protobuf.Struct getMetadata() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * A key/value object to store custom metadata about a task.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(3, getStatus()); - } - for (int i = 0; i < artifacts_.size(); i++) { - output.writeMessage(4, artifacts_.get(i)); - } - for (int i = 0; i < history_.size(); i++) { - output.writeMessage(5, history_.get(i)); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeMessage(6, getMetadata()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getStatus()); - } - for (int i = 0; i < artifacts_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, artifacts_.get(i)); - } - for (int i = 0; i < history_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, history_.get(i)); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getMetadata()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.Task)) { - return super.equals(obj); - } - io.a2a.grpc.Task other = (io.a2a.grpc.Task) obj; - - if (!getId() - .equals(other.getId())) return false; - if (!getContextId() - .equals(other.getContextId())) return false; - if (hasStatus() != other.hasStatus()) return false; - if (hasStatus()) { - if (!getStatus() - .equals(other.getStatus())) return false; - } - if (!getArtifactsList() - .equals(other.getArtifactsList())) return false; - if (!getHistoryList() - .equals(other.getHistoryList())) return false; - if (hasMetadata() != other.hasMetadata()) return false; - if (hasMetadata()) { - if (!getMetadata() - .equals(other.getMetadata())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; - hash = (53 * hash) + getContextId().hashCode(); - if (hasStatus()) { - hash = (37 * hash) + STATUS_FIELD_NUMBER; - hash = (53 * hash) + getStatus().hashCode(); - } - if (getArtifactsCount() > 0) { - hash = (37 * hash) + ARTIFACTS_FIELD_NUMBER; - hash = (53 * hash) + getArtifactsList().hashCode(); - } - if (getHistoryCount() > 0) { - hash = (37 * hash) + HISTORY_FIELD_NUMBER; - hash = (53 * hash) + getHistoryList().hashCode(); - } - if (hasMetadata()) { - hash = (37 * hash) + METADATA_FIELD_NUMBER; - hash = (53 * hash) + getMetadata().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.Task parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Task parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Task parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Task parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Task parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.Task parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.Task parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Task parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.Task parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.Task parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.Task parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.Task parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.Task prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:Task]
-   * Task is the core unit of action for A2A. It has a current status
-   * and when results are created for the task they are stored in the
-   * artifact. If there are multiple turns for a task, these are stored in
-   * history.
-   * 
- * - * Protobuf type {@code a2a.v1.Task} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.Task) - io.a2a.grpc.TaskOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.Task.class, io.a2a.grpc.Task.Builder.class); - } - - // Construct using io.a2a.grpc.Task.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetStatusFieldBuilder(); - internalGetArtifactsFieldBuilder(); - internalGetHistoryFieldBuilder(); - internalGetMetadataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - id_ = ""; - contextId_ = ""; - status_ = null; - if (statusBuilder_ != null) { - statusBuilder_.dispose(); - statusBuilder_ = null; - } - if (artifactsBuilder_ == null) { - artifacts_ = java.util.Collections.emptyList(); - } else { - artifacts_ = null; - artifactsBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000008); - if (historyBuilder_ == null) { - history_ = java.util.Collections.emptyList(); - } else { - history_ = null; - historyBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000010); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_Task_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.Task getDefaultInstanceForType() { - return io.a2a.grpc.Task.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.Task build() { - io.a2a.grpc.Task result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.Task buildPartial() { - io.a2a.grpc.Task result = new io.a2a.grpc.Task(this); - buildPartialRepeatedFields(result); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartialRepeatedFields(io.a2a.grpc.Task result) { - if (artifactsBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0)) { - artifacts_ = java.util.Collections.unmodifiableList(artifacts_); - bitField0_ = (bitField0_ & ~0x00000008); - } - result.artifacts_ = artifacts_; - } else { - result.artifacts_ = artifactsBuilder_.build(); - } - if (historyBuilder_ == null) { - if (((bitField0_ & 0x00000010) != 0)) { - history_ = java.util.Collections.unmodifiableList(history_); - bitField0_ = (bitField0_ & ~0x00000010); - } - result.history_ = history_; - } else { - result.history_ = historyBuilder_.build(); - } - } - - private void buildPartial0(io.a2a.grpc.Task result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.id_ = id_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.contextId_ = contextId_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.status_ = statusBuilder_ == null - ? status_ - : statusBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000020) != 0)) { - result.metadata_ = metadataBuilder_ == null - ? metadata_ - : metadataBuilder_.build(); - to_bitField0_ |= 0x00000002; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.Task) { - return mergeFrom((io.a2a.grpc.Task)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.Task other) { - if (other == io.a2a.grpc.Task.getDefaultInstance()) return this; - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getContextId().isEmpty()) { - contextId_ = other.contextId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.hasStatus()) { - mergeStatus(other.getStatus()); - } - if (artifactsBuilder_ == null) { - if (!other.artifacts_.isEmpty()) { - if (artifacts_.isEmpty()) { - artifacts_ = other.artifacts_; - bitField0_ = (bitField0_ & ~0x00000008); - } else { - ensureArtifactsIsMutable(); - artifacts_.addAll(other.artifacts_); - } - onChanged(); - } - } else { - if (!other.artifacts_.isEmpty()) { - if (artifactsBuilder_.isEmpty()) { - artifactsBuilder_.dispose(); - artifactsBuilder_ = null; - artifacts_ = other.artifacts_; - bitField0_ = (bitField0_ & ~0x00000008); - artifactsBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetArtifactsFieldBuilder() : null; - } else { - artifactsBuilder_.addAllMessages(other.artifacts_); - } - } - } - if (historyBuilder_ == null) { - if (!other.history_.isEmpty()) { - if (history_.isEmpty()) { - history_ = other.history_; - bitField0_ = (bitField0_ & ~0x00000010); - } else { - ensureHistoryIsMutable(); - history_.addAll(other.history_); - } - onChanged(); - } - } else { - if (!other.history_.isEmpty()) { - if (historyBuilder_.isEmpty()) { - historyBuilder_.dispose(); - historyBuilder_ = null; - history_ = other.history_; - bitField0_ = (bitField0_ & ~0x00000010); - historyBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - internalGetHistoryFieldBuilder() : null; - } else { - historyBuilder_.addAllMessages(other.history_); - } - } - } - if (other.hasMetadata()) { - mergeMetadata(other.getMetadata()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - contextId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetStatusFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - io.a2a.grpc.Artifact m = - input.readMessage( - io.a2a.grpc.Artifact.parser(), - extensionRegistry); - if (artifactsBuilder_ == null) { - ensureArtifactsIsMutable(); - artifacts_.add(m); - } else { - artifactsBuilder_.addMessage(m); - } - break; - } // case 34 - case 42: { - io.a2a.grpc.Message m = - input.readMessage( - io.a2a.grpc.Message.parser(), - extensionRegistry); - if (historyBuilder_ == null) { - ensureHistoryIsMutable(); - history_.add(m); - } else { - historyBuilder_.addMessage(m); - } - break; - } // case 42 - case 50: { - input.readMessage( - internalGetMetadataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000020; - break; - } // case 50 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object id_ = ""; - /** - *
-     * Unique identifier (e.g. UUID) for the task, generated by the server for a
-     * new task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Unique identifier (e.g. UUID) for the task, generated by the server for a
-     * new task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Unique identifier (e.g. UUID) for the task, generated by the server for a
-     * new task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Unique identifier (e.g. UUID) for the task, generated by the server for a
-     * new task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Unique identifier (e.g. UUID) for the task, generated by the server for a
-     * new task.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object contextId_ = ""; - /** - *
-     * Unique identifier (e.g. UUID) for the contextual collection of interactions
-     * (tasks and messages). Created by the A2A server.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Unique identifier (e.g. UUID) for the contextual collection of interactions
-     * (tasks and messages). Created by the A2A server.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Unique identifier (e.g. UUID) for the contextual collection of interactions
-     * (tasks and messages). Created by the A2A server.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The contextId to set. - * @return This builder for chaining. - */ - public Builder setContextId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * Unique identifier (e.g. UUID) for the contextual collection of interactions
-     * (tasks and messages). Created by the A2A server.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearContextId() { - contextId_ = getDefaultInstance().getContextId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * Unique identifier (e.g. UUID) for the contextual collection of interactions
-     * (tasks and messages). Created by the A2A server.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for contextId to set. - * @return This builder for chaining. - */ - public Builder setContextIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private io.a2a.grpc.TaskStatus status_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> statusBuilder_; - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the status field is set. - */ - public boolean hasStatus() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The status. - */ - public io.a2a.grpc.TaskStatus getStatus() { - if (statusBuilder_ == null) { - return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } else { - return statusBuilder_.getMessage(); - } - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setStatus(io.a2a.grpc.TaskStatus value) { - if (statusBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - status_ = value; - } else { - statusBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setStatus( - io.a2a.grpc.TaskStatus.Builder builderForValue) { - if (statusBuilder_ == null) { - status_ = builderForValue.build(); - } else { - statusBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeStatus(io.a2a.grpc.TaskStatus value) { - if (statusBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - status_ != null && - status_ != io.a2a.grpc.TaskStatus.getDefaultInstance()) { - getStatusBuilder().mergeFrom(value); - } else { - status_ = value; - } - } else { - statusBuilder_.mergeFrom(value); - } - if (status_ != null) { - bitField0_ |= 0x00000004; - onChanged(); - } - return this; - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearStatus() { - bitField0_ = (bitField0_ & ~0x00000004); - status_ = null; - if (statusBuilder_ != null) { - statusBuilder_.dispose(); - statusBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return internalGetStatusFieldBuilder().getBuilder(); - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { - if (statusBuilder_ != null) { - return statusBuilder_.getMessageOrBuilder(); - } else { - return status_ == null ? - io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } - } - /** - *
-     * The current status of a Task, including state and a message.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> - internalGetStatusFieldBuilder() { - if (statusBuilder_ == null) { - statusBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder>( - getStatus(), - getParentForChildren(), - isClean()); - status_ = null; - } - return statusBuilder_; - } - - private java.util.List artifacts_ = - java.util.Collections.emptyList(); - private void ensureArtifactsIsMutable() { - if (!((bitField0_ & 0x00000008) != 0)) { - artifacts_ = new java.util.ArrayList(artifacts_); - bitField0_ |= 0x00000008; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> artifactsBuilder_; - - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public java.util.List getArtifactsList() { - if (artifactsBuilder_ == null) { - return java.util.Collections.unmodifiableList(artifacts_); - } else { - return artifactsBuilder_.getMessageList(); - } - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public int getArtifactsCount() { - if (artifactsBuilder_ == null) { - return artifacts_.size(); - } else { - return artifactsBuilder_.getCount(); - } - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public io.a2a.grpc.Artifact getArtifacts(int index) { - if (artifactsBuilder_ == null) { - return artifacts_.get(index); - } else { - return artifactsBuilder_.getMessage(index); - } - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder setArtifacts( - int index, io.a2a.grpc.Artifact value) { - if (artifactsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureArtifactsIsMutable(); - artifacts_.set(index, value); - onChanged(); - } else { - artifactsBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder setArtifacts( - int index, io.a2a.grpc.Artifact.Builder builderForValue) { - if (artifactsBuilder_ == null) { - ensureArtifactsIsMutable(); - artifacts_.set(index, builderForValue.build()); - onChanged(); - } else { - artifactsBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder addArtifacts(io.a2a.grpc.Artifact value) { - if (artifactsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureArtifactsIsMutable(); - artifacts_.add(value); - onChanged(); - } else { - artifactsBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder addArtifacts( - int index, io.a2a.grpc.Artifact value) { - if (artifactsBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureArtifactsIsMutable(); - artifacts_.add(index, value); - onChanged(); - } else { - artifactsBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder addArtifacts( - io.a2a.grpc.Artifact.Builder builderForValue) { - if (artifactsBuilder_ == null) { - ensureArtifactsIsMutable(); - artifacts_.add(builderForValue.build()); - onChanged(); - } else { - artifactsBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder addArtifacts( - int index, io.a2a.grpc.Artifact.Builder builderForValue) { - if (artifactsBuilder_ == null) { - ensureArtifactsIsMutable(); - artifacts_.add(index, builderForValue.build()); - onChanged(); - } else { - artifactsBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder addAllArtifacts( - java.lang.Iterable values) { - if (artifactsBuilder_ == null) { - ensureArtifactsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, artifacts_); - onChanged(); - } else { - artifactsBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder clearArtifacts() { - if (artifactsBuilder_ == null) { - artifacts_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); - onChanged(); - } else { - artifactsBuilder_.clear(); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public Builder removeArtifacts(int index) { - if (artifactsBuilder_ == null) { - ensureArtifactsIsMutable(); - artifacts_.remove(index); - onChanged(); - } else { - artifactsBuilder_.remove(index); - } - return this; - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public io.a2a.grpc.Artifact.Builder getArtifactsBuilder( - int index) { - return internalGetArtifactsFieldBuilder().getBuilder(index); - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( - int index) { - if (artifactsBuilder_ == null) { - return artifacts_.get(index); } else { - return artifactsBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public java.util.List - getArtifactsOrBuilderList() { - if (artifactsBuilder_ != null) { - return artifactsBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(artifacts_); - } - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public io.a2a.grpc.Artifact.Builder addArtifactsBuilder() { - return internalGetArtifactsFieldBuilder().addBuilder( - io.a2a.grpc.Artifact.getDefaultInstance()); - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public io.a2a.grpc.Artifact.Builder addArtifactsBuilder( - int index) { - return internalGetArtifactsFieldBuilder().addBuilder( - index, io.a2a.grpc.Artifact.getDefaultInstance()); - } - /** - *
-     * A set of output artifacts for a Task.
-     * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - public java.util.List - getArtifactsBuilderList() { - return internalGetArtifactsFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> - internalGetArtifactsFieldBuilder() { - if (artifactsBuilder_ == null) { - artifactsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder>( - artifacts_, - ((bitField0_ & 0x00000008) != 0), - getParentForChildren(), - isClean()); - artifacts_ = null; - } - return artifactsBuilder_; - } - - private java.util.List history_ = - java.util.Collections.emptyList(); - private void ensureHistoryIsMutable() { - if (!((bitField0_ & 0x00000010) != 0)) { - history_ = new java.util.ArrayList(history_); - bitField0_ |= 0x00000010; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> historyBuilder_; - - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public java.util.List getHistoryList() { - if (historyBuilder_ == null) { - return java.util.Collections.unmodifiableList(history_); - } else { - return historyBuilder_.getMessageList(); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public int getHistoryCount() { - if (historyBuilder_ == null) { - return history_.size(); - } else { - return historyBuilder_.getCount(); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public io.a2a.grpc.Message getHistory(int index) { - if (historyBuilder_ == null) { - return history_.get(index); - } else { - return historyBuilder_.getMessage(index); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder setHistory( - int index, io.a2a.grpc.Message value) { - if (historyBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureHistoryIsMutable(); - history_.set(index, value); - onChanged(); - } else { - historyBuilder_.setMessage(index, value); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder setHistory( - int index, io.a2a.grpc.Message.Builder builderForValue) { - if (historyBuilder_ == null) { - ensureHistoryIsMutable(); - history_.set(index, builderForValue.build()); - onChanged(); - } else { - historyBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder addHistory(io.a2a.grpc.Message value) { - if (historyBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureHistoryIsMutable(); - history_.add(value); - onChanged(); - } else { - historyBuilder_.addMessage(value); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder addHistory( - int index, io.a2a.grpc.Message value) { - if (historyBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureHistoryIsMutable(); - history_.add(index, value); - onChanged(); - } else { - historyBuilder_.addMessage(index, value); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder addHistory( - io.a2a.grpc.Message.Builder builderForValue) { - if (historyBuilder_ == null) { - ensureHistoryIsMutable(); - history_.add(builderForValue.build()); - onChanged(); - } else { - historyBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder addHistory( - int index, io.a2a.grpc.Message.Builder builderForValue) { - if (historyBuilder_ == null) { - ensureHistoryIsMutable(); - history_.add(index, builderForValue.build()); - onChanged(); - } else { - historyBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder addAllHistory( - java.lang.Iterable values) { - if (historyBuilder_ == null) { - ensureHistoryIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, history_); - onChanged(); - } else { - historyBuilder_.addAllMessages(values); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder clearHistory() { - if (historyBuilder_ == null) { - history_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000010); - onChanged(); - } else { - historyBuilder_.clear(); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public Builder removeHistory(int index) { - if (historyBuilder_ == null) { - ensureHistoryIsMutable(); - history_.remove(index); - onChanged(); - } else { - historyBuilder_.remove(index); - } - return this; - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public io.a2a.grpc.Message.Builder getHistoryBuilder( - int index) { - return internalGetHistoryFieldBuilder().getBuilder(index); - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( - int index) { - if (historyBuilder_ == null) { - return history_.get(index); } else { - return historyBuilder_.getMessageOrBuilder(index); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public java.util.List - getHistoryOrBuilderList() { - if (historyBuilder_ != null) { - return historyBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(history_); - } - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public io.a2a.grpc.Message.Builder addHistoryBuilder() { - return internalGetHistoryFieldBuilder().addBuilder( - io.a2a.grpc.Message.getDefaultInstance()); - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public io.a2a.grpc.Message.Builder addHistoryBuilder( - int index) { - return internalGetHistoryFieldBuilder().addBuilder( - index, io.a2a.grpc.Message.getDefaultInstance()); - } - /** - *
-     * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-     * The history of interactions from a task.
-     * 
- * - * repeated .a2a.v1.Message history = 5; - */ - public java.util.List - getHistoryBuilderList() { - return internalGetHistoryFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> - internalGetHistoryFieldBuilder() { - if (historyBuilder_ == null) { - historyBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>( - history_, - ((bitField0_ & 0x00000010) != 0), - getParentForChildren(), - isClean()); - history_ = null; - } - return historyBuilder_; - } - - private com.google.protobuf.Struct metadata_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - public boolean hasMetadata() { - return ((bitField0_ & 0x00000020) != 0); - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - public com.google.protobuf.Struct getMetadata() { - if (metadataBuilder_ == null) { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } else { - return metadataBuilder_.getMessage(); - } - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - metadata_ = value; - } else { - metadataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata( - com.google.protobuf.Struct.Builder builderForValue) { - if (metadataBuilder_ == null) { - metadata_ = builderForValue.build(); - } else { - metadataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder mergeMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000020) != 0) && - metadata_ != null && - metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { - getMetadataBuilder().mergeFrom(value); - } else { - metadata_ = value; - } - } else { - metadataBuilder_.mergeFrom(value); - } - if (metadata_ != null) { - bitField0_ |= 0x00000020; - onChanged(); - } - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000020); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000020; - onChanged(); - return internalGetMetadataFieldBuilder().getBuilder(); - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - if (metadataBuilder_ != null) { - return metadataBuilder_.getMessageOrBuilder(); - } else { - return metadata_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - } - /** - *
-     * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-     * A key/value object to store custom metadata about a task.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetMetadataFieldBuilder() { - if (metadataBuilder_ == null) { - metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getMetadata(), - getParentForChildren(), - isClean()); - metadata_ = null; - } - return metadataBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.Task) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.Task) - private static final io.a2a.grpc.Task DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.Task(); - } - - public static io.a2a.grpc.Task getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public Task parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.Task getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java deleted file mode 100644 index 08be9ee0c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEvent.java +++ /dev/null @@ -1,1350 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:TaskArtifactUpdateEvent]
- * TaskArtifactUpdateEvent represents a task delta where an artifact has
- * been generated.
- * 
- * - * Protobuf type {@code a2a.v1.TaskArtifactUpdateEvent} - */ -@com.google.protobuf.Generated -public final class TaskArtifactUpdateEvent extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskArtifactUpdateEvent) - TaskArtifactUpdateEventOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "TaskArtifactUpdateEvent"); - } - // Use TaskArtifactUpdateEvent.newBuilder() to construct. - private TaskArtifactUpdateEvent(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private TaskArtifactUpdateEvent() { - taskId_ = ""; - contextId_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskArtifactUpdateEvent.class, io.a2a.grpc.TaskArtifactUpdateEvent.Builder.class); - } - - private int bitField0_; - public static final int TASK_ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The id of the task for this artifact.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The id of the task for this artifact.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONTEXT_ID_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object contextId_ = ""; - /** - *
-   * The id of the context that this task belongs to.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - @java.lang.Override - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } - } - /** - *
-   * The id of the context that this task belongs to.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ARTIFACT_FIELD_NUMBER = 3; - private io.a2a.grpc.Artifact artifact_; - /** - *
-   * The artifact that was generated or updated.
-   * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the artifact field is set. - */ - @java.lang.Override - public boolean hasArtifact() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The artifact that was generated or updated.
-   * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The artifact. - */ - @java.lang.Override - public io.a2a.grpc.Artifact getArtifact() { - return artifact_ == null ? io.a2a.grpc.Artifact.getDefaultInstance() : artifact_; - } - /** - *
-   * The artifact that was generated or updated.
-   * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() { - return artifact_ == null ? io.a2a.grpc.Artifact.getDefaultInstance() : artifact_; - } - - public static final int APPEND_FIELD_NUMBER = 4; - private boolean append_ = false; - /** - *
-   * If true, the content of this artifact should be appended to a previously
-   * sent artifact with the same ID.
-   * 
- * - * bool append = 4; - * @return The append. - */ - @java.lang.Override - public boolean getAppend() { - return append_; - } - - public static final int LAST_CHUNK_FIELD_NUMBER = 5; - private boolean lastChunk_ = false; - /** - *
-   * If true, this is the final chunk of the artifact.
-   * 
- * - * bool last_chunk = 5; - * @return The lastChunk. - */ - @java.lang.Override - public boolean getLastChunk() { - return lastChunk_; - } - - public static final int METADATA_FIELD_NUMBER = 6; - private com.google.protobuf.Struct metadata_; - /** - *
-   * Optional metadata associated with the artifact update.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - @java.lang.Override - public boolean hasMetadata() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * Optional metadata associated with the artifact update.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - @java.lang.Override - public com.google.protobuf.Struct getMetadata() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - /** - *
-   * Optional metadata associated with the artifact update.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(3, getArtifact()); - } - if (append_ != false) { - output.writeBool(4, append_); - } - if (lastChunk_ != false) { - output.writeBool(5, lastChunk_); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeMessage(6, getMetadata()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getArtifact()); - } - if (append_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(4, append_); - } - if (lastChunk_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(5, lastChunk_); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, getMetadata()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.TaskArtifactUpdateEvent)) { - return super.equals(obj); - } - io.a2a.grpc.TaskArtifactUpdateEvent other = (io.a2a.grpc.TaskArtifactUpdateEvent) obj; - - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (!getContextId() - .equals(other.getContextId())) return false; - if (hasArtifact() != other.hasArtifact()) return false; - if (hasArtifact()) { - if (!getArtifact() - .equals(other.getArtifact())) return false; - } - if (getAppend() - != other.getAppend()) return false; - if (getLastChunk() - != other.getLastChunk()) return false; - if (hasMetadata() != other.hasMetadata()) return false; - if (hasMetadata()) { - if (!getMetadata() - .equals(other.getMetadata())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; - hash = (53 * hash) + getContextId().hashCode(); - if (hasArtifact()) { - hash = (37 * hash) + ARTIFACT_FIELD_NUMBER; - hash = (53 * hash) + getArtifact().hashCode(); - } - hash = (37 * hash) + APPEND_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getAppend()); - hash = (37 * hash) + LAST_CHUNK_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getLastChunk()); - if (hasMetadata()) { - hash = (37 * hash) + METADATA_FIELD_NUMBER; - hash = (53 * hash) + getMetadata().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.TaskArtifactUpdateEvent parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.TaskArtifactUpdateEvent parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskArtifactUpdateEvent parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.TaskArtifactUpdateEvent prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:TaskArtifactUpdateEvent]
-   * TaskArtifactUpdateEvent represents a task delta where an artifact has
-   * been generated.
-   * 
- * - * Protobuf type {@code a2a.v1.TaskArtifactUpdateEvent} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskArtifactUpdateEvent) - io.a2a.grpc.TaskArtifactUpdateEventOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskArtifactUpdateEvent.class, io.a2a.grpc.TaskArtifactUpdateEvent.Builder.class); - } - - // Construct using io.a2a.grpc.TaskArtifactUpdateEvent.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetArtifactFieldBuilder(); - internalGetMetadataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - taskId_ = ""; - contextId_ = ""; - artifact_ = null; - if (artifactBuilder_ != null) { - artifactBuilder_.dispose(); - artifactBuilder_ = null; - } - append_ = false; - lastChunk_ = false; - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskArtifactUpdateEvent_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() { - return io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEvent build() { - io.a2a.grpc.TaskArtifactUpdateEvent result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEvent buildPartial() { - io.a2a.grpc.TaskArtifactUpdateEvent result = new io.a2a.grpc.TaskArtifactUpdateEvent(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.TaskArtifactUpdateEvent result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.taskId_ = taskId_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.contextId_ = contextId_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.artifact_ = artifactBuilder_ == null - ? artifact_ - : artifactBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.append_ = append_; - } - if (((from_bitField0_ & 0x00000010) != 0)) { - result.lastChunk_ = lastChunk_; - } - if (((from_bitField0_ & 0x00000020) != 0)) { - result.metadata_ = metadataBuilder_ == null - ? metadata_ - : metadataBuilder_.build(); - to_bitField0_ |= 0x00000002; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.TaskArtifactUpdateEvent) { - return mergeFrom((io.a2a.grpc.TaskArtifactUpdateEvent)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.TaskArtifactUpdateEvent other) { - if (other == io.a2a.grpc.TaskArtifactUpdateEvent.getDefaultInstance()) return this; - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getContextId().isEmpty()) { - contextId_ = other.contextId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.hasArtifact()) { - mergeArtifact(other.getArtifact()); - } - if (other.getAppend() != false) { - setAppend(other.getAppend()); - } - if (other.getLastChunk() != false) { - setLastChunk(other.getLastChunk()); - } - if (other.hasMetadata()) { - mergeMetadata(other.getMetadata()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - contextId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetArtifactFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 32: { - append_ = input.readBool(); - bitField0_ |= 0x00000008; - break; - } // case 32 - case 40: { - lastChunk_ = input.readBool(); - bitField0_ |= 0x00000010; - break; - } // case 40 - case 50: { - input.readMessage( - internalGetMetadataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000020; - break; - } // case 50 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object taskId_ = ""; - /** - *
-     * The id of the task for this artifact.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The id of the task for this artifact.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The id of the task for this artifact.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The id of the task for this artifact.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The id of the task for this artifact.
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object contextId_ = ""; - /** - *
-     * The id of the context that this task belongs to.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The id of the context that this task belongs to.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The id of the context that this task belongs to.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The contextId to set. - * @return This builder for chaining. - */ - public Builder setContextId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The id of the context that this task belongs to.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearContextId() { - contextId_ = getDefaultInstance().getContextId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The id of the context that this task belongs to.
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for contextId to set. - * @return This builder for chaining. - */ - public Builder setContextIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private io.a2a.grpc.Artifact artifact_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> artifactBuilder_; - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the artifact field is set. - */ - public boolean hasArtifact() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The artifact. - */ - public io.a2a.grpc.Artifact getArtifact() { - if (artifactBuilder_ == null) { - return artifact_ == null ? io.a2a.grpc.Artifact.getDefaultInstance() : artifact_; - } else { - return artifactBuilder_.getMessage(); - } - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setArtifact(io.a2a.grpc.Artifact value) { - if (artifactBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - artifact_ = value; - } else { - artifactBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setArtifact( - io.a2a.grpc.Artifact.Builder builderForValue) { - if (artifactBuilder_ == null) { - artifact_ = builderForValue.build(); - } else { - artifactBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeArtifact(io.a2a.grpc.Artifact value) { - if (artifactBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - artifact_ != null && - artifact_ != io.a2a.grpc.Artifact.getDefaultInstance()) { - getArtifactBuilder().mergeFrom(value); - } else { - artifact_ = value; - } - } else { - artifactBuilder_.mergeFrom(value); - } - if (artifact_ != null) { - bitField0_ |= 0x00000004; - onChanged(); - } - return this; - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearArtifact() { - bitField0_ = (bitField0_ & ~0x00000004); - artifact_ = null; - if (artifactBuilder_ != null) { - artifactBuilder_.dispose(); - artifactBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.Artifact.Builder getArtifactBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return internalGetArtifactFieldBuilder().getBuilder(); - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder() { - if (artifactBuilder_ != null) { - return artifactBuilder_.getMessageOrBuilder(); - } else { - return artifact_ == null ? - io.a2a.grpc.Artifact.getDefaultInstance() : artifact_; - } - } - /** - *
-     * The artifact that was generated or updated.
-     * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder> - internalGetArtifactFieldBuilder() { - if (artifactBuilder_ == null) { - artifactBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Artifact, io.a2a.grpc.Artifact.Builder, io.a2a.grpc.ArtifactOrBuilder>( - getArtifact(), - getParentForChildren(), - isClean()); - artifact_ = null; - } - return artifactBuilder_; - } - - private boolean append_ ; - /** - *
-     * If true, the content of this artifact should be appended to a previously
-     * sent artifact with the same ID.
-     * 
- * - * bool append = 4; - * @return The append. - */ - @java.lang.Override - public boolean getAppend() { - return append_; - } - /** - *
-     * If true, the content of this artifact should be appended to a previously
-     * sent artifact with the same ID.
-     * 
- * - * bool append = 4; - * @param value The append to set. - * @return This builder for chaining. - */ - public Builder setAppend(boolean value) { - - append_ = value; - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * If true, the content of this artifact should be appended to a previously
-     * sent artifact with the same ID.
-     * 
- * - * bool append = 4; - * @return This builder for chaining. - */ - public Builder clearAppend() { - bitField0_ = (bitField0_ & ~0x00000008); - append_ = false; - onChanged(); - return this; - } - - private boolean lastChunk_ ; - /** - *
-     * If true, this is the final chunk of the artifact.
-     * 
- * - * bool last_chunk = 5; - * @return The lastChunk. - */ - @java.lang.Override - public boolean getLastChunk() { - return lastChunk_; - } - /** - *
-     * If true, this is the final chunk of the artifact.
-     * 
- * - * bool last_chunk = 5; - * @param value The lastChunk to set. - * @return This builder for chaining. - */ - public Builder setLastChunk(boolean value) { - - lastChunk_ = value; - bitField0_ |= 0x00000010; - onChanged(); - return this; - } - /** - *
-     * If true, this is the final chunk of the artifact.
-     * 
- * - * bool last_chunk = 5; - * @return This builder for chaining. - */ - public Builder clearLastChunk() { - bitField0_ = (bitField0_ & ~0x00000010); - lastChunk_ = false; - onChanged(); - return this; - } - - private com.google.protobuf.Struct metadata_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - public boolean hasMetadata() { - return ((bitField0_ & 0x00000020) != 0); - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - public com.google.protobuf.Struct getMetadata() { - if (metadataBuilder_ == null) { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } else { - return metadataBuilder_.getMessage(); - } - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - metadata_ = value; - } else { - metadataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder setMetadata( - com.google.protobuf.Struct.Builder builderForValue) { - if (metadataBuilder_ == null) { - metadata_ = builderForValue.build(); - } else { - metadataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000020; - onChanged(); - return this; - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder mergeMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000020) != 0) && - metadata_ != null && - metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { - getMetadataBuilder().mergeFrom(value); - } else { - metadata_ = value; - } - } else { - metadataBuilder_.mergeFrom(value); - } - if (metadata_ != null) { - bitField0_ |= 0x00000020; - onChanged(); - } - return this; - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000020); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000020; - onChanged(); - return internalGetMetadataFieldBuilder().getBuilder(); - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - if (metadataBuilder_ != null) { - return metadataBuilder_.getMessageOrBuilder(); - } else { - return metadata_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - } - /** - *
-     * Optional metadata associated with the artifact update.
-     * 
- * - * .google.protobuf.Struct metadata = 6; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetMetadataFieldBuilder() { - if (metadataBuilder_ == null) { - metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getMetadata(), - getParentForChildren(), - isClean()); - metadata_ = null; - } - return metadataBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskArtifactUpdateEvent) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.TaskArtifactUpdateEvent) - private static final io.a2a.grpc.TaskArtifactUpdateEvent DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.TaskArtifactUpdateEvent(); - } - - public static io.a2a.grpc.TaskArtifactUpdateEvent getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TaskArtifactUpdateEvent parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.TaskArtifactUpdateEvent getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java deleted file mode 100644 index 97b99f5d1..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskArtifactUpdateEventOrBuilder.java +++ /dev/null @@ -1,127 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface TaskArtifactUpdateEventOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskArtifactUpdateEvent) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The id of the task for this artifact.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The id of the task for this artifact.
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * The id of the context that this task belongs to.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - java.lang.String getContextId(); - /** - *
-   * The id of the context that this task belongs to.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - com.google.protobuf.ByteString - getContextIdBytes(); - - /** - *
-   * The artifact that was generated or updated.
-   * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the artifact field is set. - */ - boolean hasArtifact(); - /** - *
-   * The artifact that was generated or updated.
-   * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The artifact. - */ - io.a2a.grpc.Artifact getArtifact(); - /** - *
-   * The artifact that was generated or updated.
-   * 
- * - * .a2a.v1.Artifact artifact = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.ArtifactOrBuilder getArtifactOrBuilder(); - - /** - *
-   * If true, the content of this artifact should be appended to a previously
-   * sent artifact with the same ID.
-   * 
- * - * bool append = 4; - * @return The append. - */ - boolean getAppend(); - - /** - *
-   * If true, this is the final chunk of the artifact.
-   * 
- * - * bool last_chunk = 5; - * @return The lastChunk. - */ - boolean getLastChunk(); - - /** - *
-   * Optional metadata associated with the artifact update.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - boolean hasMetadata(); - /** - *
-   * Optional metadata associated with the artifact update.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - com.google.protobuf.Struct getMetadata(); - /** - *
-   * Optional metadata associated with the artifact update.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java deleted file mode 100644 index 2c8648576..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskOrBuilder.java +++ /dev/null @@ -1,206 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface TaskOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.Task) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Unique identifier (e.g. UUID) for the task, generated by the server for a
-   * new task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * Unique identifier (e.g. UUID) for the task, generated by the server for a
-   * new task.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - *
-   * Unique identifier (e.g. UUID) for the contextual collection of interactions
-   * (tasks and messages). Created by the A2A server.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - java.lang.String getContextId(); - /** - *
-   * Unique identifier (e.g. UUID) for the contextual collection of interactions
-   * (tasks and messages). Created by the A2A server.
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - com.google.protobuf.ByteString - getContextIdBytes(); - - /** - *
-   * The current status of a Task, including state and a message.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the status field is set. - */ - boolean hasStatus(); - /** - *
-   * The current status of a Task, including state and a message.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The status. - */ - io.a2a.grpc.TaskStatus getStatus(); - /** - *
-   * The current status of a Task, including state and a message.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder(); - - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - java.util.List - getArtifactsList(); - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - io.a2a.grpc.Artifact getArtifacts(int index); - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - int getArtifactsCount(); - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - java.util.List - getArtifactsOrBuilderList(); - /** - *
-   * A set of output artifacts for a Task.
-   * 
- * - * repeated .a2a.v1.Artifact artifacts = 4; - */ - io.a2a.grpc.ArtifactOrBuilder getArtifactsOrBuilder( - int index); - - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - java.util.List - getHistoryList(); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - io.a2a.grpc.Message getHistory(int index); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - int getHistoryCount(); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - java.util.List - getHistoryOrBuilderList(); - /** - *
-   * protolint:disable REPEATED_FIELD_NAMES_PLURALIZED
-   * The history of interactions from a task.
-   * 
- * - * repeated .a2a.v1.Message history = 5; - */ - io.a2a.grpc.MessageOrBuilder getHistoryOrBuilder( - int index); - - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * A key/value object to store custom metadata about a task.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return Whether the metadata field is set. - */ - boolean hasMetadata(); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * A key/value object to store custom metadata about a task.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - * @return The metadata. - */ - com.google.protobuf.Struct getMetadata(); - /** - *
-   * protolint:enable REPEATED_FIELD_NAMES_PLURALIZED
-   * A key/value object to store custom metadata about a task.
-   * 
- * - * .google.protobuf.Struct metadata = 6; - */ - com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java deleted file mode 100644 index 745594565..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfig.java +++ /dev/null @@ -1,1111 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:TaskPushNotificationConfig]
- * A container associating a push notification configuration with a specific
- * task.
- * 
- * - * Protobuf type {@code a2a.v1.TaskPushNotificationConfig} - */ -@com.google.protobuf.Generated -public final class TaskPushNotificationConfig extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskPushNotificationConfig) - TaskPushNotificationConfigOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "TaskPushNotificationConfig"); - } - // Use TaskPushNotificationConfig.newBuilder() to construct. - private TaskPushNotificationConfig(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private TaskPushNotificationConfig() { - tenant_ = ""; - id_ = ""; - taskId_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskPushNotificationConfig.class, io.a2a.grpc.TaskPushNotificationConfig.Builder.class); - } - - private int bitField0_; - public static final int TENANT_FIELD_NUMBER = 4; - @SuppressWarnings("serial") - private volatile java.lang.Object tenant_ = ""; - /** - *
-   * Optional tenant
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - @java.lang.Override - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } - } - /** - *
-   * Optional tenant
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object id_ = ""; - /** - *
-   * The id of the config.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - @java.lang.Override - public java.lang.String getId() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } - } - /** - *
-   * The id of the config.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TASK_ID_FIELD_NUMBER = 3; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The id of the task this config is associated with.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The id of the task this config is associated with.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER = 2; - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; - /** - *
-   * The push notification configuration details.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the pushNotificationConfig field is set. - */ - @java.lang.Override - public boolean hasPushNotificationConfig() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The push notification configuration details.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The pushNotificationConfig. - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } - /** - *
-   * The push notification configuration details.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, id_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(2, getPushNotificationConfig()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 3, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 4, tenant_); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(id_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, id_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getPushNotificationConfig()); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(3, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(tenant_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(4, tenant_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.TaskPushNotificationConfig)) { - return super.equals(obj); - } - io.a2a.grpc.TaskPushNotificationConfig other = (io.a2a.grpc.TaskPushNotificationConfig) obj; - - if (!getTenant() - .equals(other.getTenant())) return false; - if (!getId() - .equals(other.getId())) return false; - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (hasPushNotificationConfig() != other.hasPushNotificationConfig()) return false; - if (hasPushNotificationConfig()) { - if (!getPushNotificationConfig() - .equals(other.getPushNotificationConfig())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TENANT_FIELD_NUMBER; - hash = (53 * hash) + getTenant().hashCode(); - hash = (37 * hash) + ID_FIELD_NUMBER; - hash = (53 * hash) + getId().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - if (hasPushNotificationConfig()) { - hash = (37 * hash) + PUSH_NOTIFICATION_CONFIG_FIELD_NUMBER; - hash = (53 * hash) + getPushNotificationConfig().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.TaskPushNotificationConfig parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.TaskPushNotificationConfig parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskPushNotificationConfig parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.TaskPushNotificationConfig prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:TaskPushNotificationConfig]
-   * A container associating a push notification configuration with a specific
-   * task.
-   * 
- * - * Protobuf type {@code a2a.v1.TaskPushNotificationConfig} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskPushNotificationConfig) - io.a2a.grpc.TaskPushNotificationConfigOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskPushNotificationConfig.class, io.a2a.grpc.TaskPushNotificationConfig.Builder.class); - } - - // Construct using io.a2a.grpc.TaskPushNotificationConfig.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetPushNotificationConfigFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - tenant_ = ""; - id_ = ""; - taskId_ = ""; - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskPushNotificationConfig_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfig getDefaultInstanceForType() { - return io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfig build() { - io.a2a.grpc.TaskPushNotificationConfig result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfig buildPartial() { - io.a2a.grpc.TaskPushNotificationConfig result = new io.a2a.grpc.TaskPushNotificationConfig(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.TaskPushNotificationConfig result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.tenant_ = tenant_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.id_ = id_; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.taskId_ = taskId_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000008) != 0)) { - result.pushNotificationConfig_ = pushNotificationConfigBuilder_ == null - ? pushNotificationConfig_ - : pushNotificationConfigBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.TaskPushNotificationConfig) { - return mergeFrom((io.a2a.grpc.TaskPushNotificationConfig)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.TaskPushNotificationConfig other) { - if (other == io.a2a.grpc.TaskPushNotificationConfig.getDefaultInstance()) return this; - if (!other.getTenant().isEmpty()) { - tenant_ = other.tenant_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getId().isEmpty()) { - id_ = other.id_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000004; - onChanged(); - } - if (other.hasPushNotificationConfig()) { - mergePushNotificationConfig(other.getPushNotificationConfig()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - id_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 10 - case 18: { - input.readMessage( - internalGetPushNotificationConfigFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 18 - case 26: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 34: { - tenant_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 34 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object tenant_ = ""; - /** - *
-     * Optional tenant
-     * 
- * - * string tenant = 4; - * @return The tenant. - */ - public java.lang.String getTenant() { - java.lang.Object ref = tenant_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - tenant_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * Optional tenant
-     * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - public com.google.protobuf.ByteString - getTenantBytes() { - java.lang.Object ref = tenant_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - tenant_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * Optional tenant
-     * 
- * - * string tenant = 4; - * @param value The tenant to set. - * @return This builder for chaining. - */ - public Builder setTenant( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * Optional tenant
-     * 
- * - * string tenant = 4; - * @return This builder for chaining. - */ - public Builder clearTenant() { - tenant_ = getDefaultInstance().getTenant(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * Optional tenant
-     * 
- * - * string tenant = 4; - * @param value The bytes for tenant to set. - * @return This builder for chaining. - */ - public Builder setTenantBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - tenant_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object id_ = ""; - /** - *
-     * The id of the config.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - public java.lang.String getId() { - java.lang.Object ref = id_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - id_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The id of the config.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - public com.google.protobuf.ByteString - getIdBytes() { - java.lang.Object ref = id_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - id_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The id of the config.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The id to set. - * @return This builder for chaining. - */ - public Builder setId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The id of the config.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearId() { - id_ = getDefaultInstance().getId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The id of the config.
-     * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for id to set. - * @return This builder for chaining. - */ - public Builder setIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - id_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private java.lang.Object taskId_ = ""; - /** - *
-     * The id of the task this config is associated with.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The id of the task this config is associated with.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The id of the task this config is associated with.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The id of the task this config is associated with.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000004); - onChanged(); - return this; - } - /** - *
-     * The id of the task this config is associated with.
-     * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - - private io.a2a.grpc.PushNotificationConfig pushNotificationConfig_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> pushNotificationConfigBuilder_; - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the pushNotificationConfig field is set. - */ - public boolean hasPushNotificationConfig() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The pushNotificationConfig. - */ - public io.a2a.grpc.PushNotificationConfig getPushNotificationConfig() { - if (pushNotificationConfigBuilder_ == null) { - return pushNotificationConfig_ == null ? io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } else { - return pushNotificationConfigBuilder_.getMessage(); - } - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setPushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - pushNotificationConfig_ = value; - } else { - pushNotificationConfigBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setPushNotificationConfig( - io.a2a.grpc.PushNotificationConfig.Builder builderForValue) { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfig_ = builderForValue.build(); - } else { - pushNotificationConfigBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergePushNotificationConfig(io.a2a.grpc.PushNotificationConfig value) { - if (pushNotificationConfigBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - pushNotificationConfig_ != null && - pushNotificationConfig_ != io.a2a.grpc.PushNotificationConfig.getDefaultInstance()) { - getPushNotificationConfigBuilder().mergeFrom(value); - } else { - pushNotificationConfig_ = value; - } - } else { - pushNotificationConfigBuilder_.mergeFrom(value); - } - if (pushNotificationConfig_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearPushNotificationConfig() { - bitField0_ = (bitField0_ & ~0x00000008); - pushNotificationConfig_ = null; - if (pushNotificationConfigBuilder_ != null) { - pushNotificationConfigBuilder_.dispose(); - pushNotificationConfigBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PushNotificationConfig.Builder getPushNotificationConfigBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetPushNotificationConfigFieldBuilder().getBuilder(); - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder() { - if (pushNotificationConfigBuilder_ != null) { - return pushNotificationConfigBuilder_.getMessageOrBuilder(); - } else { - return pushNotificationConfig_ == null ? - io.a2a.grpc.PushNotificationConfig.getDefaultInstance() : pushNotificationConfig_; - } - } - /** - *
-     * The push notification configuration details.
-     * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder> - internalGetPushNotificationConfigFieldBuilder() { - if (pushNotificationConfigBuilder_ == null) { - pushNotificationConfigBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.PushNotificationConfig, io.a2a.grpc.PushNotificationConfig.Builder, io.a2a.grpc.PushNotificationConfigOrBuilder>( - getPushNotificationConfig(), - getParentForChildren(), - isClean()); - pushNotificationConfig_ = null; - } - return pushNotificationConfigBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskPushNotificationConfig) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.TaskPushNotificationConfig) - private static final io.a2a.grpc.TaskPushNotificationConfig DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.TaskPushNotificationConfig(); - } - - public static io.a2a.grpc.TaskPushNotificationConfig getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TaskPushNotificationConfig parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.TaskPushNotificationConfig getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java deleted file mode 100644 index 2da32ae41..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskPushNotificationConfigOrBuilder.java +++ /dev/null @@ -1,99 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface TaskPushNotificationConfigOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskPushNotificationConfig) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * Optional tenant
-   * 
- * - * string tenant = 4; - * @return The tenant. - */ - java.lang.String getTenant(); - /** - *
-   * Optional tenant
-   * 
- * - * string tenant = 4; - * @return The bytes for tenant. - */ - com.google.protobuf.ByteString - getTenantBytes(); - - /** - *
-   * The id of the config.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The id. - */ - java.lang.String getId(); - /** - *
-   * The id of the config.
-   * 
- * - * string id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for id. - */ - com.google.protobuf.ByteString - getIdBytes(); - - /** - *
-   * The id of the task this config is associated with.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The id of the task this config is associated with.
-   * 
- * - * string task_id = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * The push notification configuration details.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the pushNotificationConfig field is set. - */ - boolean hasPushNotificationConfig(); - /** - *
-   * The push notification configuration details.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The pushNotificationConfig. - */ - io.a2a.grpc.PushNotificationConfig getPushNotificationConfig(); - /** - *
-   * The push notification configuration details.
-   * 
- * - * .a2a.v1.PushNotificationConfig push_notification_config = 2 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.PushNotificationConfigOrBuilder getPushNotificationConfigOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java deleted file mode 100644 index 9fc6b6441..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskState.java +++ /dev/null @@ -1,275 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:TaskState]
- * Defines the possible lifecycle states of a Task.
- * 
- * - * Protobuf enum {@code a2a.v1.TaskState} - */ -@com.google.protobuf.Generated -public enum TaskState - implements com.google.protobuf.ProtocolMessageEnum { - /** - *
-   * The task is in an unknown or indeterminate state.
-   * 
- * - * TASK_STATE_UNSPECIFIED = 0; - */ - TASK_STATE_UNSPECIFIED(0), - /** - *
-   * Represents the status that acknowledges a task is created.
-   * 
- * - * TASK_STATE_SUBMITTED = 1; - */ - TASK_STATE_SUBMITTED(1), - /** - *
-   * Represents the status that a task is actively being processed.
-   * 
- * - * TASK_STATE_WORKING = 2; - */ - TASK_STATE_WORKING(2), - /** - *
-   * Represents the status a task is finished. This is a terminal state.
-   * 
- * - * TASK_STATE_COMPLETED = 3; - */ - TASK_STATE_COMPLETED(3), - /** - *
-   * Represents the status a task is done but failed. This is a terminal state.
-   * 
- * - * TASK_STATE_FAILED = 4; - */ - TASK_STATE_FAILED(4), - /** - *
-   * Represents the status a task was canceled before it finished.
-   * This is a terminal state.
-   * 
- * - * TASK_STATE_CANCELED = 5; - */ - TASK_STATE_CANCELED(5), - /** - *
-   * Represents the status that the task requires information to complete.
-   * This is an interrupted state.
-   * 
- * - * TASK_STATE_INPUT_REQUIRED = 6; - */ - TASK_STATE_INPUT_REQUIRED(6), - /** - *
-   * Represents the status that the agent has decided to not perform the task.
-   * This may be done during initial task creation or later once an agent
-   * has determined it can't or won't proceed. This is a terminal state.
-   * 
- * - * TASK_STATE_REJECTED = 7; - */ - TASK_STATE_REJECTED(7), - /** - *
-   * Represents the state that some authentication is needed from the upstream
-   * client. This is an interrupted state. Authentication is expected to come out-of-band.
-   * 
- * - * TASK_STATE_AUTH_REQUIRED = 8; - */ - TASK_STATE_AUTH_REQUIRED(8), - UNRECOGNIZED(-1), - ; - - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "TaskState"); - } - /** - *
-   * The task is in an unknown or indeterminate state.
-   * 
- * - * TASK_STATE_UNSPECIFIED = 0; - */ - public static final int TASK_STATE_UNSPECIFIED_VALUE = 0; - /** - *
-   * Represents the status that acknowledges a task is created.
-   * 
- * - * TASK_STATE_SUBMITTED = 1; - */ - public static final int TASK_STATE_SUBMITTED_VALUE = 1; - /** - *
-   * Represents the status that a task is actively being processed.
-   * 
- * - * TASK_STATE_WORKING = 2; - */ - public static final int TASK_STATE_WORKING_VALUE = 2; - /** - *
-   * Represents the status a task is finished. This is a terminal state.
-   * 
- * - * TASK_STATE_COMPLETED = 3; - */ - public static final int TASK_STATE_COMPLETED_VALUE = 3; - /** - *
-   * Represents the status a task is done but failed. This is a terminal state.
-   * 
- * - * TASK_STATE_FAILED = 4; - */ - public static final int TASK_STATE_FAILED_VALUE = 4; - /** - *
-   * Represents the status a task was canceled before it finished.
-   * This is a terminal state.
-   * 
- * - * TASK_STATE_CANCELED = 5; - */ - public static final int TASK_STATE_CANCELED_VALUE = 5; - /** - *
-   * Represents the status that the task requires information to complete.
-   * This is an interrupted state.
-   * 
- * - * TASK_STATE_INPUT_REQUIRED = 6; - */ - public static final int TASK_STATE_INPUT_REQUIRED_VALUE = 6; - /** - *
-   * Represents the status that the agent has decided to not perform the task.
-   * This may be done during initial task creation or later once an agent
-   * has determined it can't or won't proceed. This is a terminal state.
-   * 
- * - * TASK_STATE_REJECTED = 7; - */ - public static final int TASK_STATE_REJECTED_VALUE = 7; - /** - *
-   * Represents the state that some authentication is needed from the upstream
-   * client. This is an interrupted state. Authentication is expected to come out-of-band.
-   * 
- * - * TASK_STATE_AUTH_REQUIRED = 8; - */ - public static final int TASK_STATE_AUTH_REQUIRED_VALUE = 8; - - - public final int getNumber() { - if (this == UNRECOGNIZED) { - throw new java.lang.IllegalArgumentException( - "Can't get the number of an unknown enum value."); - } - return value; - } - - /** - * @param value The numeric wire value of the corresponding enum entry. - * @return The enum associated with the given numeric wire value. - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static TaskState valueOf(int value) { - return forNumber(value); - } - - /** - * @param value The numeric wire value of the corresponding enum entry. - * @return The enum associated with the given numeric wire value. - */ - public static TaskState forNumber(int value) { - switch (value) { - case 0: return TASK_STATE_UNSPECIFIED; - case 1: return TASK_STATE_SUBMITTED; - case 2: return TASK_STATE_WORKING; - case 3: return TASK_STATE_COMPLETED; - case 4: return TASK_STATE_FAILED; - case 5: return TASK_STATE_CANCELED; - case 6: return TASK_STATE_INPUT_REQUIRED; - case 7: return TASK_STATE_REJECTED; - case 8: return TASK_STATE_AUTH_REQUIRED; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static final com.google.protobuf.Internal.EnumLiteMap< - TaskState> internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public TaskState findValueByNumber(int number) { - return TaskState.forNumber(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - if (this == UNRECOGNIZED) { - throw new java.lang.IllegalStateException( - "Can't get the descriptor of an unrecognized enum value."); - } - return getDescriptor().getValues().get(ordinal()); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return io.a2a.grpc.A2A.getDescriptor().getEnumTypes().get(0); - } - - private static final TaskState[] VALUES = values(); - - public static TaskState valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - if (desc.getIndex() == -1) { - return UNRECOGNIZED; - } - return VALUES[desc.getIndex()]; - } - - private final int value; - - private TaskState(int value) { - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:a2a.v1.TaskState) -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java deleted file mode 100644 index d435fbb50..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatus.java +++ /dev/null @@ -1,982 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:TaskStatus]
- * A container for the status of a task
- * 
- * - * Protobuf type {@code a2a.v1.TaskStatus} - */ -@com.google.protobuf.Generated -public final class TaskStatus extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskStatus) - TaskStatusOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "TaskStatus"); - } - // Use TaskStatus.newBuilder() to construct. - private TaskStatus(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private TaskStatus() { - state_ = 0; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskStatus.class, io.a2a.grpc.TaskStatus.Builder.class); - } - - private int bitField0_; - public static final int STATE_FIELD_NUMBER = 1; - private int state_ = 0; - /** - *
-   * The current state of this task.
-   * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The enum numeric value on the wire for state. - */ - @java.lang.Override public int getStateValue() { - return state_; - } - /** - *
-   * The current state of this task.
-   * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The state. - */ - @java.lang.Override public io.a2a.grpc.TaskState getState() { - io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(state_); - return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result; - } - - public static final int MESSAGE_FIELD_NUMBER = 2; - private io.a2a.grpc.Message message_; - /** - *
-   * A message associated with the status.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - @java.lang.Override - public boolean hasMessage() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * A message associated with the status.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return The message. - */ - @java.lang.Override - public io.a2a.grpc.Message getMessage() { - return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; - } - /** - *
-   * A message associated with the status.
-   * 
- * - * .a2a.v1.Message message = 2; - */ - @java.lang.Override - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; - } - - public static final int TIMESTAMP_FIELD_NUMBER = 3; - private com.google.protobuf.Timestamp timestamp_; - /** - *
-   * ISO 8601 Timestamp when the status was recorded.
-   * Example: "2023-10-27T10:00:00Z"
-   * 
- * - * .google.protobuf.Timestamp timestamp = 3; - * @return Whether the timestamp field is set. - */ - @java.lang.Override - public boolean hasTimestamp() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * ISO 8601 Timestamp when the status was recorded.
-   * Example: "2023-10-27T10:00:00Z"
-   * 
- * - * .google.protobuf.Timestamp timestamp = 3; - * @return The timestamp. - */ - @java.lang.Override - public com.google.protobuf.Timestamp getTimestamp() { - return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; - } - /** - *
-   * ISO 8601 Timestamp when the status was recorded.
-   * Example: "2023-10-27T10:00:00Z"
-   * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - @java.lang.Override - public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() { - return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (state_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { - output.writeEnum(1, state_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(2, getMessage()); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeMessage(3, getTimestamp()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (state_ != io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED.getNumber()) { - size += com.google.protobuf.CodedOutputStream - .computeEnumSize(1, state_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getMessage()); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getTimestamp()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.TaskStatus)) { - return super.equals(obj); - } - io.a2a.grpc.TaskStatus other = (io.a2a.grpc.TaskStatus) obj; - - if (state_ != other.state_) return false; - if (hasMessage() != other.hasMessage()) return false; - if (hasMessage()) { - if (!getMessage() - .equals(other.getMessage())) return false; - } - if (hasTimestamp() != other.hasTimestamp()) return false; - if (hasTimestamp()) { - if (!getTimestamp() - .equals(other.getTimestamp())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + STATE_FIELD_NUMBER; - hash = (53 * hash) + state_; - if (hasMessage()) { - hash = (37 * hash) + MESSAGE_FIELD_NUMBER; - hash = (53 * hash) + getMessage().hashCode(); - } - if (hasTimestamp()) { - hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + getTimestamp().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.TaskStatus parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskStatus parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskStatus parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskStatus parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskStatus parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskStatus parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskStatus parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskStatus parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.TaskStatus parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.TaskStatus parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.TaskStatus parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskStatus parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.TaskStatus prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:TaskStatus]
-   * A container for the status of a task
-   * 
- * - * Protobuf type {@code a2a.v1.TaskStatus} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskStatus) - io.a2a.grpc.TaskStatusOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskStatus.class, io.a2a.grpc.TaskStatus.Builder.class); - } - - // Construct using io.a2a.grpc.TaskStatus.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetMessageFieldBuilder(); - internalGetTimestampFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - state_ = 0; - message_ = null; - if (messageBuilder_ != null) { - messageBuilder_.dispose(); - messageBuilder_ = null; - } - timestamp_ = null; - if (timestampBuilder_ != null) { - timestampBuilder_.dispose(); - timestampBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatus_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.TaskStatus getDefaultInstanceForType() { - return io.a2a.grpc.TaskStatus.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.TaskStatus build() { - io.a2a.grpc.TaskStatus result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.TaskStatus buildPartial() { - io.a2a.grpc.TaskStatus result = new io.a2a.grpc.TaskStatus(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.TaskStatus result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.state_ = state_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000002) != 0)) { - result.message_ = messageBuilder_ == null - ? message_ - : messageBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000004) != 0)) { - result.timestamp_ = timestampBuilder_ == null - ? timestamp_ - : timestampBuilder_.build(); - to_bitField0_ |= 0x00000002; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.TaskStatus) { - return mergeFrom((io.a2a.grpc.TaskStatus)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.TaskStatus other) { - if (other == io.a2a.grpc.TaskStatus.getDefaultInstance()) return this; - if (other.state_ != 0) { - setStateValue(other.getStateValue()); - } - if (other.hasMessage()) { - mergeMessage(other.getMessage()); - } - if (other.hasTimestamp()) { - mergeTimestamp(other.getTimestamp()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 8: { - state_ = input.readEnum(); - bitField0_ |= 0x00000001; - break; - } // case 8 - case 18: { - input.readMessage( - internalGetMessageFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetTimestampFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000004; - break; - } // case 26 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private int state_ = 0; - /** - *
-     * The current state of this task.
-     * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The enum numeric value on the wire for state. - */ - @java.lang.Override public int getStateValue() { - return state_; - } - /** - *
-     * The current state of this task.
-     * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The enum numeric value on the wire for state to set. - * @return This builder for chaining. - */ - public Builder setStateValue(int value) { - state_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The current state of this task.
-     * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The state. - */ - @java.lang.Override - public io.a2a.grpc.TaskState getState() { - io.a2a.grpc.TaskState result = io.a2a.grpc.TaskState.forNumber(state_); - return result == null ? io.a2a.grpc.TaskState.UNRECOGNIZED : result; - } - /** - *
-     * The current state of this task.
-     * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The state to set. - * @return This builder for chaining. - */ - public Builder setState(io.a2a.grpc.TaskState value) { - if (value == null) { throw new NullPointerException(); } - bitField0_ |= 0x00000001; - state_ = value.getNumber(); - onChanged(); - return this; - } - /** - *
-     * The current state of this task.
-     * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearState() { - bitField0_ = (bitField0_ & ~0x00000001); - state_ = 0; - onChanged(); - return this; - } - - private io.a2a.grpc.Message message_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> messageBuilder_; - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - public boolean hasMessage() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - * @return The message. - */ - public io.a2a.grpc.Message getMessage() { - if (messageBuilder_ == null) { - return message_ == null ? io.a2a.grpc.Message.getDefaultInstance() : message_; - } else { - return messageBuilder_.getMessage(); - } - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder setMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - message_ = value; - } else { - messageBuilder_.setMessage(value); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder setMessage( - io.a2a.grpc.Message.Builder builderForValue) { - if (messageBuilder_ == null) { - message_ = builderForValue.build(); - } else { - messageBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder mergeMessage(io.a2a.grpc.Message value) { - if (messageBuilder_ == null) { - if (((bitField0_ & 0x00000002) != 0) && - message_ != null && - message_ != io.a2a.grpc.Message.getDefaultInstance()) { - getMessageBuilder().mergeFrom(value); - } else { - message_ = value; - } - } else { - messageBuilder_.mergeFrom(value); - } - if (message_ != null) { - bitField0_ |= 0x00000002; - onChanged(); - } - return this; - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public Builder clearMessage() { - bitField0_ = (bitField0_ & ~0x00000002); - message_ = null; - if (messageBuilder_ != null) { - messageBuilder_.dispose(); - messageBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public io.a2a.grpc.Message.Builder getMessageBuilder() { - bitField0_ |= 0x00000002; - onChanged(); - return internalGetMessageFieldBuilder().getBuilder(); - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - public io.a2a.grpc.MessageOrBuilder getMessageOrBuilder() { - if (messageBuilder_ != null) { - return messageBuilder_.getMessageOrBuilder(); - } else { - return message_ == null ? - io.a2a.grpc.Message.getDefaultInstance() : message_; - } - } - /** - *
-     * A message associated with the status.
-     * 
- * - * .a2a.v1.Message message = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder> - internalGetMessageFieldBuilder() { - if (messageBuilder_ == null) { - messageBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.Message, io.a2a.grpc.Message.Builder, io.a2a.grpc.MessageOrBuilder>( - getMessage(), - getParentForChildren(), - isClean()); - message_ = null; - } - return messageBuilder_; - } - - private com.google.protobuf.Timestamp timestamp_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> timestampBuilder_; - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - * @return Whether the timestamp field is set. - */ - public boolean hasTimestamp() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - * @return The timestamp. - */ - public com.google.protobuf.Timestamp getTimestamp() { - if (timestampBuilder_ == null) { - return timestamp_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; - } else { - return timestampBuilder_.getMessage(); - } - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - public Builder setTimestamp(com.google.protobuf.Timestamp value) { - if (timestampBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - timestamp_ = value; - } else { - timestampBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - public Builder setTimestamp( - com.google.protobuf.Timestamp.Builder builderForValue) { - if (timestampBuilder_ == null) { - timestamp_ = builderForValue.build(); - } else { - timestampBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - public Builder mergeTimestamp(com.google.protobuf.Timestamp value) { - if (timestampBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - timestamp_ != null && - timestamp_ != com.google.protobuf.Timestamp.getDefaultInstance()) { - getTimestampBuilder().mergeFrom(value); - } else { - timestamp_ = value; - } - } else { - timestampBuilder_.mergeFrom(value); - } - if (timestamp_ != null) { - bitField0_ |= 0x00000004; - onChanged(); - } - return this; - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - public Builder clearTimestamp() { - bitField0_ = (bitField0_ & ~0x00000004); - timestamp_ = null; - if (timestampBuilder_ != null) { - timestampBuilder_.dispose(); - timestampBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - public com.google.protobuf.Timestamp.Builder getTimestampBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return internalGetTimestampFieldBuilder().getBuilder(); - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - public com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder() { - if (timestampBuilder_ != null) { - return timestampBuilder_.getMessageOrBuilder(); - } else { - return timestamp_ == null ? - com.google.protobuf.Timestamp.getDefaultInstance() : timestamp_; - } - } - /** - *
-     * ISO 8601 Timestamp when the status was recorded.
-     * Example: "2023-10-27T10:00:00Z"
-     * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder> - internalGetTimestampFieldBuilder() { - if (timestampBuilder_ == null) { - timestampBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Timestamp, com.google.protobuf.Timestamp.Builder, com.google.protobuf.TimestampOrBuilder>( - getTimestamp(), - getParentForChildren(), - isClean()); - timestamp_ = null; - } - return timestampBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskStatus) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.TaskStatus) - private static final io.a2a.grpc.TaskStatus DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.TaskStatus(); - } - - public static io.a2a.grpc.TaskStatus getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TaskStatus parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.TaskStatus getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java deleted file mode 100644 index fc9d5434b..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusOrBuilder.java +++ /dev/null @@ -1,88 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface TaskStatusOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskStatus) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The current state of this task.
-   * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The enum numeric value on the wire for state. - */ - int getStateValue(); - /** - *
-   * The current state of this task.
-   * 
- * - * .a2a.v1.TaskState state = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The state. - */ - io.a2a.grpc.TaskState getState(); - - /** - *
-   * A message associated with the status.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return Whether the message field is set. - */ - boolean hasMessage(); - /** - *
-   * A message associated with the status.
-   * 
- * - * .a2a.v1.Message message = 2; - * @return The message. - */ - io.a2a.grpc.Message getMessage(); - /** - *
-   * A message associated with the status.
-   * 
- * - * .a2a.v1.Message message = 2; - */ - io.a2a.grpc.MessageOrBuilder getMessageOrBuilder(); - - /** - *
-   * ISO 8601 Timestamp when the status was recorded.
-   * Example: "2023-10-27T10:00:00Z"
-   * 
- * - * .google.protobuf.Timestamp timestamp = 3; - * @return Whether the timestamp field is set. - */ - boolean hasTimestamp(); - /** - *
-   * ISO 8601 Timestamp when the status was recorded.
-   * Example: "2023-10-27T10:00:00Z"
-   * 
- * - * .google.protobuf.Timestamp timestamp = 3; - * @return The timestamp. - */ - com.google.protobuf.Timestamp getTimestamp(); - /** - *
-   * ISO 8601 Timestamp when the status was recorded.
-   * Example: "2023-10-27T10:00:00Z"
-   * 
- * - * .google.protobuf.Timestamp timestamp = 3; - */ - com.google.protobuf.TimestampOrBuilder getTimestampOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java deleted file mode 100644 index 06cb104e0..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEvent.java +++ /dev/null @@ -1,1180 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -/** - *
- * --8<-- [start:TaskStatusUpdateEvent]
- * An event sent by the agent to notify the client of a change in a task's
- * status.
- * 
- * - * Protobuf type {@code a2a.v1.TaskStatusUpdateEvent} - */ -@com.google.protobuf.Generated -public final class TaskStatusUpdateEvent extends - com.google.protobuf.GeneratedMessage implements - // @@protoc_insertion_point(message_implements:a2a.v1.TaskStatusUpdateEvent) - TaskStatusUpdateEventOrBuilder { -private static final long serialVersionUID = 0L; - static { - com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( - com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, - /* major= */ 4, - /* minor= */ 33, - /* patch= */ 1, - /* suffix= */ "", - "TaskStatusUpdateEvent"); - } - // Use TaskStatusUpdateEvent.newBuilder() to construct. - private TaskStatusUpdateEvent(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - } - private TaskStatusUpdateEvent() { - taskId_ = ""; - contextId_ = ""; - } - - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskStatusUpdateEvent.class, io.a2a.grpc.TaskStatusUpdateEvent.Builder.class); - } - - private int bitField0_; - public static final int TASK_ID_FIELD_NUMBER = 1; - @SuppressWarnings("serial") - private volatile java.lang.Object taskId_ = ""; - /** - *
-   * The id of the task that is changed
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - @java.lang.Override - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } - } - /** - *
-   * The id of the task that is changed
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CONTEXT_ID_FIELD_NUMBER = 2; - @SuppressWarnings("serial") - private volatile java.lang.Object contextId_ = ""; - /** - *
-   * The id of the context that the task belongs to
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - @java.lang.Override - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } - } - /** - *
-   * The id of the context that the task belongs to
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - @java.lang.Override - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int STATUS_FIELD_NUMBER = 3; - private io.a2a.grpc.TaskStatus status_; - /** - *
-   * The new status of the task.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the status field is set. - */ - @java.lang.Override - public boolean hasStatus() { - return ((bitField0_ & 0x00000001) != 0); - } - /** - *
-   * The new status of the task.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The status. - */ - @java.lang.Override - public io.a2a.grpc.TaskStatus getStatus() { - return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } - /** - *
-   * The new status of the task.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - @java.lang.Override - public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { - return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } - - public static final int METADATA_FIELD_NUMBER = 5; - private com.google.protobuf.Struct metadata_; - /** - *
-   * Optional metadata to associate with the task update.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return Whether the metadata field is set. - */ - @java.lang.Override - public boolean hasMetadata() { - return ((bitField0_ & 0x00000002) != 0); - } - /** - *
-   * Optional metadata to associate with the task update.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return The metadata. - */ - @java.lang.Override - public com.google.protobuf.Struct getMetadata() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - /** - *
-   * Optional metadata to associate with the task update.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - */ - @java.lang.Override - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - com.google.protobuf.GeneratedMessage.writeString(output, 2, contextId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - output.writeMessage(3, getStatus()); - } - if (((bitField0_ & 0x00000002) != 0)) { - output.writeMessage(5, getMetadata()); - } - getUnknownFields().writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(taskId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(1, taskId_); - } - if (!com.google.protobuf.GeneratedMessage.isStringEmpty(contextId_)) { - size += com.google.protobuf.GeneratedMessage.computeStringSize(2, contextId_); - } - if (((bitField0_ & 0x00000001) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, getStatus()); - } - if (((bitField0_ & 0x00000002) != 0)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, getMetadata()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.a2a.grpc.TaskStatusUpdateEvent)) { - return super.equals(obj); - } - io.a2a.grpc.TaskStatusUpdateEvent other = (io.a2a.grpc.TaskStatusUpdateEvent) obj; - - if (!getTaskId() - .equals(other.getTaskId())) return false; - if (!getContextId() - .equals(other.getContextId())) return false; - if (hasStatus() != other.hasStatus()) return false; - if (hasStatus()) { - if (!getStatus() - .equals(other.getStatus())) return false; - } - if (hasMetadata() != other.hasMetadata()) return false; - if (hasMetadata()) { - if (!getMetadata() - .equals(other.getMetadata())) return false; - } - if (!getUnknownFields().equals(other.getUnknownFields())) return false; - return true; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + TASK_ID_FIELD_NUMBER; - hash = (53 * hash) + getTaskId().hashCode(); - hash = (37 * hash) + CONTEXT_ID_FIELD_NUMBER; - hash = (53 * hash) + getContextId().hashCode(); - if (hasStatus()) { - hash = (37 * hash) + STATUS_FIELD_NUMBER; - hash = (53 * hash) + getStatus().hashCode(); - } - if (hasMetadata()) { - hash = (37 * hash) + METADATA_FIELD_NUMBER; - hash = (53 * hash) + getMetadata().hashCode(); - } - hash = (29 * hash) + getUnknownFields().hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.a2a.grpc.TaskStatusUpdateEvent parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.a2a.grpc.TaskStatusUpdateEvent parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input); - } - public static io.a2a.grpc.TaskStatusUpdateEvent parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessage - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(io.a2a.grpc.TaskStatusUpdateEvent prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - *
-   * --8<-- [start:TaskStatusUpdateEvent]
-   * An event sent by the agent to notify the client of a change in a task's
-   * status.
-   * 
- * - * Protobuf type {@code a2a.v1.TaskStatusUpdateEvent} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder implements - // @@protoc_insertion_point(builder_implements:a2a.v1.TaskStatusUpdateEvent) - io.a2a.grpc.TaskStatusUpdateEventOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.a2a.grpc.TaskStatusUpdateEvent.class, io.a2a.grpc.TaskStatusUpdateEvent.Builder.class); - } - - // Construct using io.a2a.grpc.TaskStatusUpdateEvent.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage - .alwaysUseFieldBuilders) { - internalGetStatusFieldBuilder(); - internalGetMetadataFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - bitField0_ = 0; - taskId_ = ""; - contextId_ = ""; - status_ = null; - if (statusBuilder_ != null) { - statusBuilder_.dispose(); - statusBuilder_ = null; - } - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return io.a2a.grpc.A2A.internal_static_a2a_v1_TaskStatusUpdateEvent_descriptor; - } - - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() { - return io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance(); - } - - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEvent build() { - io.a2a.grpc.TaskStatusUpdateEvent result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEvent buildPartial() { - io.a2a.grpc.TaskStatusUpdateEvent result = new io.a2a.grpc.TaskStatusUpdateEvent(this); - if (bitField0_ != 0) { buildPartial0(result); } - onBuilt(); - return result; - } - - private void buildPartial0(io.a2a.grpc.TaskStatusUpdateEvent result) { - int from_bitField0_ = bitField0_; - if (((from_bitField0_ & 0x00000001) != 0)) { - result.taskId_ = taskId_; - } - if (((from_bitField0_ & 0x00000002) != 0)) { - result.contextId_ = contextId_; - } - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000004) != 0)) { - result.status_ = statusBuilder_ == null - ? status_ - : statusBuilder_.build(); - to_bitField0_ |= 0x00000001; - } - if (((from_bitField0_ & 0x00000008) != 0)) { - result.metadata_ = metadataBuilder_ == null - ? metadata_ - : metadataBuilder_.build(); - to_bitField0_ |= 0x00000002; - } - result.bitField0_ |= to_bitField0_; - } - - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.a2a.grpc.TaskStatusUpdateEvent) { - return mergeFrom((io.a2a.grpc.TaskStatusUpdateEvent)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.a2a.grpc.TaskStatusUpdateEvent other) { - if (other == io.a2a.grpc.TaskStatusUpdateEvent.getDefaultInstance()) return this; - if (!other.getTaskId().isEmpty()) { - taskId_ = other.taskId_; - bitField0_ |= 0x00000001; - onChanged(); - } - if (!other.getContextId().isEmpty()) { - contextId_ = other.contextId_; - bitField0_ |= 0x00000002; - onChanged(); - } - if (other.hasStatus()) { - mergeStatus(other.getStatus()); - } - if (other.hasMetadata()) { - mergeMetadata(other.getMetadata()); - } - this.mergeUnknownFields(other.getUnknownFields()); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - taskId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000001; - break; - } // case 10 - case 18: { - contextId_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000002; - break; - } // case 18 - case 26: { - input.readMessage( - internalGetStatusFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000004; - break; - } // case 26 - case 42: { - input.readMessage( - internalGetMetadataFieldBuilder().getBuilder(), - extensionRegistry); - bitField0_ |= 0x00000008; - break; - } // case 42 - default: { - if (!super.parseUnknownField(input, extensionRegistry, tag)) { - done = true; // was an endgroup tag - } - break; - } // default: - } // switch (tag) - } // while (!done) - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } finally { - onChanged(); - } // finally - return this; - } - private int bitField0_; - - private java.lang.Object taskId_ = ""; - /** - *
-     * The id of the task that is changed
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - public java.lang.String getTaskId() { - java.lang.Object ref = taskId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - taskId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The id of the task that is changed
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - public com.google.protobuf.ByteString - getTaskIdBytes() { - java.lang.Object ref = taskId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - taskId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The id of the task that is changed
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - taskId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - /** - *
-     * The id of the task that is changed
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearTaskId() { - taskId_ = getDefaultInstance().getTaskId(); - bitField0_ = (bitField0_ & ~0x00000001); - onChanged(); - return this; - } - /** - *
-     * The id of the task that is changed
-     * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for taskId to set. - * @return This builder for chaining. - */ - public Builder setTaskIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - taskId_ = value; - bitField0_ |= 0x00000001; - onChanged(); - return this; - } - - private java.lang.Object contextId_ = ""; - /** - *
-     * The id of the context that the task belongs to
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - public java.lang.String getContextId() { - java.lang.Object ref = contextId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - contextId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - *
-     * The id of the context that the task belongs to
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - public com.google.protobuf.ByteString - getContextIdBytes() { - java.lang.Object ref = contextId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - contextId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - *
-     * The id of the context that the task belongs to
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The contextId to set. - * @return This builder for chaining. - */ - public Builder setContextId( - java.lang.String value) { - if (value == null) { throw new NullPointerException(); } - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - /** - *
-     * The id of the context that the task belongs to
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return This builder for chaining. - */ - public Builder clearContextId() { - contextId_ = getDefaultInstance().getContextId(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - return this; - } - /** - *
-     * The id of the context that the task belongs to
-     * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @param value The bytes for contextId to set. - * @return This builder for chaining. - */ - public Builder setContextIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { throw new NullPointerException(); } - checkByteStringIsUtf8(value); - contextId_ = value; - bitField0_ |= 0x00000002; - onChanged(); - return this; - } - - private io.a2a.grpc.TaskStatus status_; - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> statusBuilder_; - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the status field is set. - */ - public boolean hasStatus() { - return ((bitField0_ & 0x00000004) != 0); - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The status. - */ - public io.a2a.grpc.TaskStatus getStatus() { - if (statusBuilder_ == null) { - return status_ == null ? io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } else { - return statusBuilder_.getMessage(); - } - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setStatus(io.a2a.grpc.TaskStatus value) { - if (statusBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - status_ = value; - } else { - statusBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder setStatus( - io.a2a.grpc.TaskStatus.Builder builderForValue) { - if (statusBuilder_ == null) { - status_ = builderForValue.build(); - } else { - statusBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - onChanged(); - return this; - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder mergeStatus(io.a2a.grpc.TaskStatus value) { - if (statusBuilder_ == null) { - if (((bitField0_ & 0x00000004) != 0) && - status_ != null && - status_ != io.a2a.grpc.TaskStatus.getDefaultInstance()) { - getStatusBuilder().mergeFrom(value); - } else { - status_ = value; - } - } else { - statusBuilder_.mergeFrom(value); - } - if (status_ != null) { - bitField0_ |= 0x00000004; - onChanged(); - } - return this; - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public Builder clearStatus() { - bitField0_ = (bitField0_ & ~0x00000004); - status_ = null; - if (statusBuilder_ != null) { - statusBuilder_.dispose(); - statusBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.TaskStatus.Builder getStatusBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return internalGetStatusFieldBuilder().getBuilder(); - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - public io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder() { - if (statusBuilder_ != null) { - return statusBuilder_.getMessageOrBuilder(); - } else { - return status_ == null ? - io.a2a.grpc.TaskStatus.getDefaultInstance() : status_; - } - } - /** - *
-     * The new status of the task.
-     * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - private com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder> - internalGetStatusFieldBuilder() { - if (statusBuilder_ == null) { - statusBuilder_ = new com.google.protobuf.SingleFieldBuilder< - io.a2a.grpc.TaskStatus, io.a2a.grpc.TaskStatus.Builder, io.a2a.grpc.TaskStatusOrBuilder>( - getStatus(), - getParentForChildren(), - isClean()); - status_ = null; - } - return statusBuilder_; - } - - private com.google.protobuf.Struct metadata_; - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> metadataBuilder_; - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - * @return Whether the metadata field is set. - */ - public boolean hasMetadata() { - return ((bitField0_ & 0x00000008) != 0); - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - * @return The metadata. - */ - public com.google.protobuf.Struct getMetadata() { - if (metadataBuilder_ == null) { - return metadata_ == null ? com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } else { - return metadataBuilder_.getMessage(); - } - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder setMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - metadata_ = value; - } else { - metadataBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder setMetadata( - com.google.protobuf.Struct.Builder builderForValue) { - if (metadataBuilder_ == null) { - metadata_ = builderForValue.build(); - } else { - metadataBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - onChanged(); - return this; - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder mergeMetadata(com.google.protobuf.Struct value) { - if (metadataBuilder_ == null) { - if (((bitField0_ & 0x00000008) != 0) && - metadata_ != null && - metadata_ != com.google.protobuf.Struct.getDefaultInstance()) { - getMetadataBuilder().mergeFrom(value); - } else { - metadata_ = value; - } - } else { - metadataBuilder_.mergeFrom(value); - } - if (metadata_ != null) { - bitField0_ |= 0x00000008; - onChanged(); - } - return this; - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public Builder clearMetadata() { - bitField0_ = (bitField0_ & ~0x00000008); - metadata_ = null; - if (metadataBuilder_ != null) { - metadataBuilder_.dispose(); - metadataBuilder_ = null; - } - onChanged(); - return this; - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public com.google.protobuf.Struct.Builder getMetadataBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return internalGetMetadataFieldBuilder().getBuilder(); - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - public com.google.protobuf.StructOrBuilder getMetadataOrBuilder() { - if (metadataBuilder_ != null) { - return metadataBuilder_.getMessageOrBuilder(); - } else { - return metadata_ == null ? - com.google.protobuf.Struct.getDefaultInstance() : metadata_; - } - } - /** - *
-     * Optional metadata to associate with the task update.
-     * 
- * - * .google.protobuf.Struct metadata = 5; - */ - private com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder> - internalGetMetadataFieldBuilder() { - if (metadataBuilder_ == null) { - metadataBuilder_ = new com.google.protobuf.SingleFieldBuilder< - com.google.protobuf.Struct, com.google.protobuf.Struct.Builder, com.google.protobuf.StructOrBuilder>( - getMetadata(), - getParentForChildren(), - isClean()); - metadata_ = null; - } - return metadataBuilder_; - } - - // @@protoc_insertion_point(builder_scope:a2a.v1.TaskStatusUpdateEvent) - } - - // @@protoc_insertion_point(class_scope:a2a.v1.TaskStatusUpdateEvent) - private static final io.a2a.grpc.TaskStatusUpdateEvent DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new io.a2a.grpc.TaskStatusUpdateEvent(); - } - - public static io.a2a.grpc.TaskStatusUpdateEvent getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public TaskStatusUpdateEvent parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - Builder builder = newBuilder(); - try { - builder.mergeFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(builder.buildPartial()); - } catch (com.google.protobuf.UninitializedMessageException e) { - throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException(e) - .setUnfinishedMessage(builder.buildPartial()); - } - return builder.buildPartial(); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public io.a2a.grpc.TaskStatusUpdateEvent getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - -} - diff --git a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java b/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java deleted file mode 100644 index 225000e2a..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/TaskStatusUpdateEventOrBuilder.java +++ /dev/null @@ -1,106 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// NO CHECKED-IN PROTOBUF GENCODE -// source: a2a.proto -// Protobuf Java Version: 4.33.1 - -package io.a2a.grpc; - -@com.google.protobuf.Generated -public interface TaskStatusUpdateEventOrBuilder extends - // @@protoc_insertion_point(interface_extends:a2a.v1.TaskStatusUpdateEvent) - com.google.protobuf.MessageOrBuilder { - - /** - *
-   * The id of the task that is changed
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The taskId. - */ - java.lang.String getTaskId(); - /** - *
-   * The id of the task that is changed
-   * 
- * - * string task_id = 1 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for taskId. - */ - com.google.protobuf.ByteString - getTaskIdBytes(); - - /** - *
-   * The id of the context that the task belongs to
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The contextId. - */ - java.lang.String getContextId(); - /** - *
-   * The id of the context that the task belongs to
-   * 
- * - * string context_id = 2 [(.google.api.field_behavior) = REQUIRED]; - * @return The bytes for contextId. - */ - com.google.protobuf.ByteString - getContextIdBytes(); - - /** - *
-   * The new status of the task.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return Whether the status field is set. - */ - boolean hasStatus(); - /** - *
-   * The new status of the task.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - * @return The status. - */ - io.a2a.grpc.TaskStatus getStatus(); - /** - *
-   * The new status of the task.
-   * 
- * - * .a2a.v1.TaskStatus status = 3 [(.google.api.field_behavior) = REQUIRED]; - */ - io.a2a.grpc.TaskStatusOrBuilder getStatusOrBuilder(); - - /** - *
-   * Optional metadata to associate with the task update.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return Whether the metadata field is set. - */ - boolean hasMetadata(); - /** - *
-   * Optional metadata to associate with the task update.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - * @return The metadata. - */ - com.google.protobuf.Struct getMetadata(); - /** - *
-   * Optional metadata to associate with the task update.
-   * 
- * - * .google.protobuf.Struct metadata = 5; - */ - com.google.protobuf.StructOrBuilder getMetadataOrBuilder(); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java deleted file mode 100644 index 15ba5f48f..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java +++ /dev/null @@ -1,458 +0,0 @@ -package io.a2a.grpc.mapper; - -import java.time.Instant; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.google.protobuf.Struct; -import com.google.protobuf.Timestamp; -import com.google.protobuf.Value; -import org.mapstruct.Mapper; -import org.mapstruct.Named; - -import io.a2a.spec.InvalidParamsError; - -/** - * Common field mapping utilities shared across all mappers. - *

- * Provides reusable conversion methods for common protobuf ↔ domain transformations: - *

    - *
  • Empty string → null conversion (protobuf optional string defaults)
  • - *
  • Timestamp conversions (OffsetDateTime ↔ Protobuf Timestamp, Instant ↔ millis)
  • - *
  • Metadata conversions (Map ↔ Protobuf Struct)
  • - *
  • Empty list → null conversion (protobuf repeated field defaults)
  • - *
  • Zero/false → null conversion (protobuf optional numeric/bool defaults)
  • - *
  • Enum → null conversion (protobuf UNSPECIFIED/UNKNOWN handling)
  • - *
- */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {TaskStateMapper.class}) -public interface A2ACommonFieldMapper { - - A2ACommonFieldMapper INSTANCE = A2AMappers.getMapper(A2ACommonFieldMapper.class); - - /** - * Converts protobuf empty strings to null for optional fields. - *

- * Protobuf optional strings return "" when unset, but domain models use null. - * Use this with {@code @Mapping(qualifiedByName = "emptyToNull")}. - * - * @param value the protobuf string value - * @return null if empty/null, otherwise the value - */ - @Named("emptyToNull") - default String emptyToNull(String value) { - return (value == null || value.isEmpty()) ? null : value; - } - - /** - * Validates that a required string field is not null or empty. - *

- * Throws an exception if the protobuf string is null or empty. - * Use this with {@code @Mapping(qualifiedByName = "requireNonEmpty")}. - * - * @param value the protobuf string value - * @return the value if not null/empty - * @throws IllegalArgumentException if value is null or empty - */ - @Named("requireNonEmpty") - default String requireNonEmpty(String value) { - if (value == null || value.isEmpty()) { - throw new InvalidParamsError("Required field cannot be null or empty"); - } - return value; - } - - /** - * Converts null strings to empty strings for protobuf. - *

- * Domain models use null for optional fields, but protobuf uses "". - * Use this with {@code @Mapping(qualifiedByName = "nullToEmpty")}. - * - * @param value the domain string value - * @return "" if null, otherwise the value - */ - @Named("nullToEmpty") - default String nullToEmpty(String value) { - return value == null ? "" : value; - } - - /** - * Converts domain OffsetDateTime to protobuf Timestamp. - *

- * Use this with {@code @Mapping(qualifiedByName = "offsetDateTimeToProtoTimestamp")}. - * - * @param dateTime the domain OffsetDateTime - * @return protobuf Timestamp, or default instance if input is null - */ - @Named("offsetDateTimeToProtoTimestamp") - default Timestamp offsetDateTimeToProtoTimestamp(OffsetDateTime dateTime) { - if (dateTime == null) { - return Timestamp.getDefaultInstance(); - } - Instant instant = dateTime.toInstant(); - return Timestamp.newBuilder() - .setSeconds(instant.getEpochSecond()) - .setNanos(instant.getNano()) - .build(); - } - - /** - * Converts protobuf Timestamp to domain OffsetDateTime (UTC). - *

- * Use this with {@code @Mapping(qualifiedByName = "protoTimestampToOffsetDateTime")}. - * - * @param timestamp the protobuf Timestamp - * @return OffsetDateTime in UTC, or null if input is null/default - */ - @Named("protoTimestampToOffsetDateTime") - default OffsetDateTime protoTimestampToOffsetDateTime(Timestamp timestamp) { - if (timestamp == null || timestamp.equals(Timestamp.getDefaultInstance())) { - return null; - } - return OffsetDateTime.ofInstant( - Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()), - ZoneOffset.UTC - ); - } - - /** - * Converts empty lists to null for optional list fields. - *

- * Protobuf repeated fields return empty list when unset, but domain models may use null. - * Use this with {@code @Mapping(qualifiedByName = "emptyListToNull")}. - * - * @param list the protobuf list - * @return null if empty/null, otherwise the list - */ - @Named("emptyListToNull") - default java.util.List emptyListToNull(java.util.List list) { - return (list == null || list.isEmpty()) ? null : list; - } - - /** - * Converts domain Map to protobuf Struct (generic conversion). - *

- * Used for any {@code Map} field that maps to protobuf Struct (header, params, etc.). - * Use this with {@code @Mapping(qualifiedByName = "mapToStruct")}. - * - * @param map the domain map - * @return protobuf Struct, or default instance if input is null - */ - @Named("mapToStruct") - default Struct mapToStruct(Map map) { - if (map == null) { - return Struct.getDefaultInstance(); - } - Struct.Builder structBuilder = Struct.newBuilder(); - map.forEach((k, v) -> structBuilder.putFields(k, objectToValue(v))); - return structBuilder.build(); - } - - /** - * Converts protobuf Struct to domain Map (generic conversion). - *

- * Used for any protobuf Struct field that maps to {@code Map} (header, params, etc.). - * Use this with {@code @Mapping(qualifiedByName = "structToMap")}. - * - * @param struct the protobuf Struct - * @return domain Map (may be null for empty Struct) - */ - @Named("structToMap") - default Map structToMap(Struct struct) { - if (struct == null || struct.getFieldsCount() == 0) { - return null; - } - return struct.getFieldsMap().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> valueToObject(e.getValue()))); - } - - /** - * Converts a Java Object to protobuf Value. - *

- * Supports String, Number, Boolean, Map, List types, and null. - * Used for struct conversion and arbitrary JSON data. - * - * @param value the Java object - * @return protobuf Value - */ - @SuppressWarnings("unchecked") - default Value objectToValue(Object value) { - Value.Builder valueBuilder = Value.newBuilder(); - if (value instanceof String) { - valueBuilder.setStringValue((String) value); - } else if (value instanceof Number) { - valueBuilder.setNumberValue(((Number) value).doubleValue()); - } else if (value instanceof Boolean) { - valueBuilder.setBoolValue((Boolean) value); - } else if (value instanceof Map) { - valueBuilder.setStructValue(mapToStruct((Map) value)); - } else if (value instanceof List) { - valueBuilder.setListValue(listToListValue((List) value)); - } - return valueBuilder.build(); - } - - /** - * Converts protobuf Value to Java Object. - *

- * Returns appropriate Java type based on Value's kind: - *

    - *
  • STRUCT_VALUE -> {@code Map}
  • - *
  • LIST_VALUE -> {@code List} - *
  • BOOL_VALUE -> {@code Boolean}
  • - *
  • NUMBER_VALUE -> {@code Double}
  • - *
  • STRING_VALUE -> {@code String}
  • - *
  • NULL_VALUE -> {@code null}
  • - * - * Used for struct conversion and arbitrary JSON data. - * - * @param value the protobuf Value - * @return Java object (String, Double, Boolean, Map, List, or null) - */ - default Object valueToObject(Value value) { - switch (value.getKindCase()) { - case STRUCT_VALUE: - if (value.getStructValue() == null) { - return null; - } - if (value.getStructValue().getFieldsCount() == 0) { - return java.util.Collections.emptyMap(); - } - return structToMap(value.getStructValue()); - case LIST_VALUE: - return value.getListValue().getValuesList().stream() - .map(this::valueToObject) - .collect(Collectors.toList()); - case BOOL_VALUE: - return value.getBoolValue(); - case NUMBER_VALUE: - return value.getNumberValue(); - case STRING_VALUE: - return value.getStringValue(); - case NULL_VALUE: - default: - return null; - } - } - - /** - * Converts Java List to protobuf ListValue. - *

    - * Used for struct conversion and arbitrary JSON data. - * - * @param list the Java list - * @return protobuf ListValue - */ - default com.google.protobuf.ListValue listToListValue(List list) { - com.google.protobuf.ListValue.Builder listValueBuilder = com.google.protobuf.ListValue.newBuilder(); - if (list != null) { - list.forEach(o -> listValueBuilder.addValues(objectToValue(o))); - } - return listValueBuilder.build(); - } - - /** - * Converts domain metadata Map to protobuf Struct. - *

    - * Used for metadata fields in Artifact, Message, Task, and Events. - * Use this with {@code @Mapping(qualifiedByName = "metadataToProto")}. - * - * @param metadata the domain metadata map - * @return protobuf Struct, or default instance if input is null - */ - @Named("metadataToProto") - default Struct metadataToProto(Map metadata) { - return mapToStruct(metadata); - } - - /** - * Converts protobuf Struct to domain metadata Map. - *

    - * Used for metadata fields in Artifact, Message, Task, and Events. - * Use this with {@code @Mapping(qualifiedByName = "metadataFromProto")}. - * - * @param struct the protobuf Struct - * @return domain metadata Map (may be null for empty Struct) - */ - @Named("metadataFromProto") - default Map metadataFromProto(Struct struct) { - if (struct == null || struct.getFieldsCount() == 0) { - return Collections.emptyMap(); - } - return structToMap(struct); - } - - // ======================================================================== - // Optional Numeric/Boolean Conversions - // ======================================================================== - /** - * Converts protobuf int to Integer, treating 0 as null (unset). - *

    - * Protobuf optional int32 fields default to 0 when unset, but domain models use null. - * Use this with {@code @Mapping(qualifiedByName = "zeroToNull")}. - * - * @param value the protobuf int value - * @return Integer or null if value is 0 - */ - @Named("zeroToNull") - default Integer zeroToNull(int value) { - return value != 0 ? value : null; - } - - /** - * Converts protobuf int to Integer, preserving all values including 0. - *

    - * Unlike zeroToNull, this method preserves 0 values, allowing compact constructor - * validation to catch invalid values (e.g., pageSize=0 must fail validation). - * For truly optional fields where 0 means "unset", use zeroToNull instead. - * Use this with {@code @Mapping(qualifiedByName = "intToIntegerOrNull")}. - * - * @param value the protobuf int value - * @return Integer (never null for primitive int input) - */ - @Named("intToIntegerOrNull") - default Integer intToIntegerOrNull(int value) { - return value; - } - - /** - * Converts protobuf long to Long, treating 0 as null (unset). - *

    - * Protobuf optional int64 fields default to 0 when unset, but domain models use null. - * Use this with {@code @Mapping(qualifiedByName = "zeroLongToNull")}. - * - * @param value the protobuf long value - * @return Long or null if value is 0 - */ - @Named("zeroLongToNull") - default Long zeroLongToNull(long value) { - return value > 0L ? value : null; - } - - /** - * Converts protobuf bool to Boolean, treating false as null (unset). - *

    - * Protobuf optional bool fields default to false when unset, but domain models use null. - * Use this with {@code @Mapping(qualifiedByName = "falseToNull")}. - * - * @param value the protobuf bool value - * @return Boolean or null if value is false - */ - @Named("falseToNull") - default Boolean falseToNull(boolean value) { - return value ? true : null; - } - - // ======================================================================== - // Instant ↔ Millis Conversions (for int64 timestamp fields) - // ======================================================================== - /** - * Converts domain Instant to protobuf milliseconds-since-epoch (int64). - *

    - * Returns 0 if input is null (protobuf default for unset int64). - * Use this with {@code @Mapping(qualifiedByName = "instantToMillis")}. - * - * @param instant the domain Instant - * @return milliseconds since epoch, or 0 if null - */ - @Named("instantToMillis") - default long instantToMillis(Instant instant) { - return instant != null ? instant.toEpochMilli() : 0L; - } - - /** - * Converts protobuf milliseconds-since-epoch (int64) to domain Instant. - *

    - * Returns null if input is 0 (protobuf default for unset field). - * Throws InvalidParamsError for negative values (invalid timestamps). - * Use this with {@code @Mapping(qualifiedByName = "millisToInstant")}. - * - * @param millis milliseconds since epoch - * @return domain Instant, or null if millis is 0 - * @throws InvalidParamsError if millis is negative - */ - @Named("millisToInstant") - default Instant millisToInstant(long millis) { - if (millis < 0L) { - throw new InvalidParamsError(null, - "Timestamp must be a non-negative number of milliseconds since epoch, but got: " + millis, - null); - } - return millis > 0L ? Instant.ofEpochMilli(millis) : null; - } - - // ======================================================================== - // Instant ↔ Timestamp Conversions (for Timestamp timestamp fields) - // ======================================================================== - /** - * Converts domain Instant to protobuf Timestamp. - *

    - * Use this with {@code @Mapping(qualifiedByName = "instantToProtoTimestamp")}. - * - * @param instant the domain Instant - * @return protobuf Timestamp, or default instance if input is null - */ - @Named("instantToProtoTimestamp") - default Timestamp instantToProtoTimestamp(Instant instant) { - if (instant == null) { - return Timestamp.getDefaultInstance(); - } - return Timestamp.newBuilder() - .setSeconds(instant.getEpochSecond()) - .setNanos(instant.getNano()) - .build(); - } - - /** - * Converts protobuf Timestamp to domain Instant. - *

    - * Use this with {@code @Mapping(qualifiedByName = "protoTimestampToInstant")}. - * - * @param timestamp the protobuf Timestamp - * @return Instant, or null if input is null/default - */ - @Named("protoTimestampToInstant") - default Instant protoTimestampToInstant(Timestamp timestamp) { - if (timestamp == null || timestamp.equals(Timestamp.getDefaultInstance())) { - return null; - } - return Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()); - } - - // ======================================================================== - // Enum Conversions (handling UNSPECIFIED/UNKNOWN) - // ======================================================================== - /** - * Converts protobuf TaskState to domain TaskState, treating UNSPECIFIED as null. - *

    - * Protobuf enums default to UNSPECIFIED (0 value) when unset, which maps to null for optional fields. - * However, UNRECOGNIZED (invalid enum values from JSON) throws InvalidParamsError for proper validation. - * Use this with {@code @Mapping(qualifiedByName = "taskStateOrNull")}. - * - * @param state the protobuf TaskState - * @return domain TaskState or null if UNSPECIFIED - * @throws InvalidParamsError if state is UNRECOGNIZED (invalid enum value) - */ - @Named("taskStateOrNull") - default io.a2a.spec.TaskState taskStateOrNull(io.a2a.grpc.TaskState state) { - if (state == null || state == io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED) { - return null; - } - // Reject invalid enum values (e.g., "INVALID_STATUS" from JSON) - if (state == io.a2a.grpc.TaskState.UNRECOGNIZED) { - String validStates = java.util.Arrays.stream(io.a2a.spec.TaskState.values()) - .filter(s -> s != io.a2a.spec.TaskState.UNRECOGNIZED) - .map(Enum::name) - .collect(java.util.stream.Collectors.joining(", ")); - throw new InvalidParamsError(null, - "Invalid task state value. Must be one of: " + validStates, - null); - } - io.a2a.spec.TaskState result = TaskStateMapper.INSTANCE.fromProto(state); - return result; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AMappers.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AMappers.java deleted file mode 100644 index 25535b158..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AMappers.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.a2a.grpc.mapper; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - -public class A2AMappers { - private static final String IMPLEMENTATION_SUFFIX = "Impl"; - - static T getMapper(Class iface) { - try { - @SuppressWarnings( "unchecked" ) - Class implementation = - (Class) iface.getClassLoader().loadClass( iface.getName() + IMPLEMENTATION_SUFFIX ); - Constructor constructor = implementation.getDeclaredConstructor(); - constructor.setAccessible( true ); - - return constructor.newInstance(); - - } catch (ClassNotFoundException | - NoSuchMethodException | - InstantiationException | - IllegalAccessException | - InvocationTargetException e) { - throw new RuntimeException(e); - } - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AProtoMapperConfig.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AProtoMapperConfig.java deleted file mode 100644 index dd7e77084..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2AProtoMapperConfig.java +++ /dev/null @@ -1,195 +0,0 @@ -package io.a2a.grpc.mapper; - -import java.nio.ByteBuffer; -import java.time.Instant; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.google.protobuf.BoolValue; -import com.google.protobuf.ByteString; -import com.google.protobuf.Int32Value; -import com.google.protobuf.Int64Value; -import com.google.protobuf.ListValue; -import com.google.protobuf.StringValue; -import com.google.protobuf.Struct; -import com.google.protobuf.Timestamp; -import com.google.protobuf.Value; -import org.mapstruct.MapperConfig; -import org.mapstruct.NullValuePropertyMappingStrategy; -import org.mapstruct.ReportingPolicy; - -@MapperConfig( - // 1. FAIL THE BUILD if fields are missing in either Spec or Proto - unmappedTargetPolicy = ReportingPolicy.ERROR, - - // 2. Use the default component model (Singleton instance pattern) - componentModel = "default", - - // 3. IGNORE null values when mapping to protobuf (builders don't accept null) - nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE -) -public interface A2AProtoMapperConfig { - - // ======================================================================== - // 1. Enum Conversions - // ======================================================================== - - default String map(io.a2a.spec.APIKeySecurityScheme.Location location) { - return location == null ? null : location.asString(); - } - - // ======================================================================== - // 2. Time & Duration - // ======================================================================== - - default Instant map(Timestamp value) { - if (value == null) return null; - return Instant.ofEpochSecond(value.getSeconds(), value.getNanos()); - } - - default Timestamp map(Instant value) { - if (value == null) return null; - return Timestamp.newBuilder() - .setSeconds(value.getEpochSecond()) - .setNanos(value.getNano()) - .build(); - } - - default java.time.Duration map(com.google.protobuf.Duration value) { - if (value == null) return null; - return java.time.Duration.ofSeconds(value.getSeconds(), value.getNanos()); - } - - default com.google.protobuf.Duration map(java.time.Duration value) { - if (value == null) return null; - return com.google.protobuf.Duration.newBuilder() - .setSeconds(value.getSeconds()) - .setNanos(value.getNano()) - .build(); - } - - // ======================================================================== - // 3. Binary Data (ByteString) - // ======================================================================== - - default byte[] map(ByteString value) { - return value == null ? null : value.toByteArray(); - } - - default ByteString map(byte[] value) { - return value == null ? null : ByteString.copyFrom(value); - } - - default ByteBuffer mapToBuffer(ByteString value) { - return value == null ? null : value.asReadOnlyByteBuffer(); - } - - default ByteString mapFromBuffer(ByteBuffer value) { - return value == null ? null : ByteString.copyFrom(value); - } - - // ======================================================================== - // 4. Nullable Wrappers (Google Wrappers) - // ======================================================================== - - // String - default String map(StringValue value) { - return value == null ? null : value.getValue(); - } - default StringValue mapString(String value) { - return value == null ? null : StringValue.of(value); - } - - // Integer - default Integer map(Int32Value value) { - return value == null ? null : value.getValue(); - } - default Int32Value mapInt(Integer value) { - return value == null ? null : Int32Value.of(value); - } - - // Long - default Long map(Int64Value value) { - return value == null ? null : value.getValue(); - } - default Int64Value mapLong(Long value) { - return value == null ? null : Int64Value.of(value); - } - - // Boolean - default Boolean map(BoolValue value) { - return value == null ? null : value.getValue(); - } - default BoolValue mapBool(Boolean value) { - return value == null ? null : BoolValue.of(value); - } - - // ======================================================================== - // 5. JSON-RPC Support (Struct & Value) - // Maps "Struct" -> Map - // Maps "Value" -> Object - // ======================================================================== - - default Map map(Struct struct) { - if (struct == null) return null; - Map map = new HashMap<>(); - for (Map.Entry entry : struct.getFieldsMap().entrySet()) { - map.put(entry.getKey(), map(entry.getValue())); - } - return map; - } - - default Struct mapStruct(Map map) { - if (map == null) return null; - Struct.Builder builder = Struct.newBuilder(); - for (Map.Entry entry : map.entrySet()) { - builder.putFields(entry.getKey(), mapValue(entry.getValue())); - } - return builder.build(); - } - - default Object map(Value value) { - if (value == null) return null; - switch (value.getKindCase()) { - case NULL_VALUE: return null; - case NUMBER_VALUE: return value.getNumberValue(); // Returns Double - case STRING_VALUE: return value.getStringValue(); - case BOOL_VALUE: return value.getBoolValue(); - case STRUCT_VALUE: return map(value.getStructValue()); - case LIST_VALUE: - return value.getListValue().getValuesList().stream() - .map(this::map) - .collect(Collectors.toList()); - default: return null; - } - } - - default Value mapValue(Object object) { - if (object == null) { - return Value.newBuilder().setNullValue(com.google.protobuf.NullValue.NULL_VALUE).build(); - } - - if (object instanceof String) return Value.newBuilder().setStringValue((String) object).build(); - if (object instanceof Boolean) return Value.newBuilder().setBoolValue((Boolean) object).build(); - if (object instanceof Number) return Value.newBuilder().setNumberValue(((Number) object).doubleValue()).build(); - if (object instanceof Map) { - // Unchecked cast is unavoidable here unless we force Map - @SuppressWarnings("unchecked") - Map map = (Map) object; - return Value.newBuilder().setStructValue(mapStruct(map)).build(); - } - if (object instanceof List) { - ListValue.Builder listBuilder = ListValue.newBuilder(); - for (Object item : (List) object) { - listBuilder.addValues(mapValue(item)); - } - return Value.newBuilder().setListValue(listBuilder).build(); - } - - // Fallback for unknown types (e.g. custom objects inside Map) -> convert to String? - // For now, throw to catch unexpected types early - throw new IllegalArgumentException("Unsupported type for Proto Value conversion: " + object.getClass().getName()); - } -} \ No newline at end of file diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/APIKeySecuritySchemeMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/APIKeySecuritySchemeMapper.java deleted file mode 100644 index 2b1a068f8..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/APIKeySecuritySchemeMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.APIKeySecurityScheme} and {@link io.a2a.grpc.APIKeySecurityScheme}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface APIKeySecuritySchemeMapper { - - APIKeySecuritySchemeMapper INSTANCE = A2AMappers.getMapper(APIKeySecuritySchemeMapper.class); - - // location enum is converted to string via ProtoMapperConfig.map(Location) - @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - io.a2a.grpc.APIKeySecurityScheme toProto(io.a2a.spec.APIKeySecurityScheme domain); - - default io.a2a.spec.APIKeySecurityScheme fromProto(io.a2a.grpc.APIKeySecurityScheme proto) { - if (proto == null) { - return null; - } - - io.a2a.spec.APIKeySecurityScheme.Location location = - io.a2a.spec.APIKeySecurityScheme.Location.fromString(proto.getLocation()); - String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - - return new io.a2a.spec.APIKeySecurityScheme(location, proto.getName(), description); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java deleted file mode 100644 index a8216fec8..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCapabilitiesMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.AgentCapabilities} and {@link io.a2a.grpc.AgentCapabilities}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {AgentExtensionMapper.class}) -public interface AgentCapabilitiesMapper { - - AgentCapabilitiesMapper INSTANCE = A2AMappers.getMapper(AgentCapabilitiesMapper.class); - - io.a2a.grpc.AgentCapabilities toProto(io.a2a.spec.AgentCapabilities domain); - - io.a2a.spec.AgentCapabilities fromProto(io.a2a.grpc.AgentCapabilities proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java deleted file mode 100644 index 268d54714..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.AgentCard} and {@link io.a2a.grpc.AgentCard}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = { - AgentProviderMapper.class, - AgentCapabilitiesMapper.class, - AgentSkillMapper.class, - SecuritySchemeMapper.class, - SecurityRequirementMapper.class, - AgentInterfaceMapper.class, - AgentCardSignatureMapper.class - }) -public interface AgentCardMapper { - - AgentCardMapper INSTANCE = A2AMappers.getMapper(AgentCardMapper.class); - - @Mapping(target = "provider", source = "provider", conditionExpression = "java(domain.provider() != null)") - @Mapping(target = "documentationUrl", source = "documentationUrl", conditionExpression = "java(domain.documentationUrl() != null)") - @Mapping(target = "iconUrl", source = "iconUrl", conditionExpression = "java(domain.iconUrl() != null)") - io.a2a.grpc.AgentCard toProto(io.a2a.spec.AgentCard domain); - - @Mapping(target = "provider", source = "provider", conditionExpression = "java(proto.hasProvider())") - @Mapping(target = "documentationUrl", source = "documentationUrl", conditionExpression = "java(!proto.getDocumentationUrl().isEmpty())") - @Mapping(target = "iconUrl", source = "iconUrl", conditionExpression = "java(!proto.getIconUrl().isEmpty())") - io.a2a.spec.AgentCard fromProto(io.a2a.grpc.AgentCard proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardSignatureMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardSignatureMapper.java deleted file mode 100644 index b8b83d35b..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentCardSignatureMapper.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.AgentCardSignature} and {@link io.a2a.grpc.AgentCardSignature}. - *

    - * Uses CommonFieldMapper for struct conversion (header field). - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {A2ACommonFieldMapper.class}) -public interface AgentCardSignatureMapper { - - AgentCardSignatureMapper INSTANCE = A2AMappers.getMapper(AgentCardSignatureMapper.class); - - /** - * Converts domain AgentCardSignature to proto AgentCardSignature. - *

    - * Maps protectedHeader → protected field and header via struct conversion. - */ - @Mapping(source = "protectedHeader", target = "protected") - @Mapping(target = "header", source = "header", conditionExpression = "java(domain.header() != null)", qualifiedByName = "mapToStruct") - io.a2a.grpc.AgentCardSignature toProto(io.a2a.spec.AgentCardSignature domain); - - /** - * Converts proto AgentCardSignature to domain AgentCardSignature. - *

    - * Maps protected field → protectedHeader and header from struct to map. - */ - @Mapping(source = "protected", target = "protectedHeader") - @Mapping(target = "header", source = "header", qualifiedByName = "structToMap") - io.a2a.spec.AgentCardSignature fromProto(io.a2a.grpc.AgentCardSignature proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentExtensionMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentExtensionMapper.java deleted file mode 100644 index c99c947c6..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentExtensionMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.AgentExtension} and {@link io.a2a.grpc.AgentExtension}. - *

    - * Uses CommonFieldMapper for struct conversion (params field). - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {A2ACommonFieldMapper.class}) -public interface AgentExtensionMapper { - - AgentExtensionMapper INSTANCE = A2AMappers.getMapper(AgentExtensionMapper.class); - - /** - * Converts domain AgentExtension to proto AgentExtension. - *

    - * Maps params field via struct conversion. - */ - @Mapping(target = "params", source = "params", conditionExpression = "java(domain.params() != null)", qualifiedByName = "mapToStruct") - io.a2a.grpc.AgentExtension toProto(io.a2a.spec.AgentExtension domain); - - /** - * Converts proto AgentExtension to domain AgentExtension. - *

    - * Maps params field from struct to map. - */ - @Mapping(target = "params", source = "params", qualifiedByName = "structToMap") - io.a2a.spec.AgentExtension fromProto(io.a2a.grpc.AgentExtension proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java deleted file mode 100644 index 184a8c346..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentInterfaceMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.AgentInterface} and {@link io.a2a.grpc.AgentInterface}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface AgentInterfaceMapper { - - AgentInterfaceMapper INSTANCE = A2AMappers.getMapper(AgentInterfaceMapper.class); - - io.a2a.grpc.AgentInterface toProto(io.a2a.spec.AgentInterface domain); - - io.a2a.spec.AgentInterface fromProto(io.a2a.grpc.AgentInterface proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentProviderMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentProviderMapper.java deleted file mode 100644 index 80766eb72..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentProviderMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.AgentProvider} and {@link io.a2a.grpc.AgentProvider}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface AgentProviderMapper { - - AgentProviderMapper INSTANCE = A2AMappers.getMapper(AgentProviderMapper.class); - - io.a2a.grpc.AgentProvider toProto(io.a2a.spec.AgentProvider domain); - - io.a2a.spec.AgentProvider fromProto(io.a2a.grpc.AgentProvider proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java deleted file mode 100644 index d56c572b8..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AgentSkillMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.AgentSkill} and {@link io.a2a.grpc.AgentSkill}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = SecurityRequirementMapper.class) -public interface AgentSkillMapper { - - AgentSkillMapper INSTANCE = A2AMappers.getMapper(AgentSkillMapper.class); - - io.a2a.grpc.AgentSkill toProto(io.a2a.spec.AgentSkill domain); - - io.a2a.spec.AgentSkill fromProto(io.a2a.grpc.AgentSkill proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ArtifactMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ArtifactMapper.java deleted file mode 100644 index b5efe8739..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ArtifactMapper.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.Artifact; -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.Artifact} and {@link io.a2a.grpc.Artifact}. - *

    - * Uses ADDER_PREFERRED strategy to use addAllExtensions() method instead of - * trying to instantiate ProtocolStringList. Enables full compile-time validation! - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {PartMapper.class, A2ACommonFieldMapper.class}) -public interface ArtifactMapper { - - ArtifactMapper INSTANCE = A2AMappers.getMapper(ArtifactMapper.class); - - /** - * Converts domain Artifact to proto Artifact. - * ADDER_PREFERRED strategy ensures MapStruct uses addAllExtensions() method. - */ - @Mapping(target = "artifactId", source = "artifactId", conditionExpression = "java(domain.artifactId() != null)") - @Mapping(target = "name", source = "name", conditionExpression = "java(domain.name() != null)") - @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.Artifact toProto(Artifact domain); - - /** - * Converts proto Artifact to domain Artifact. - * Handles empty string → null and Struct conversions via CommonFieldMapper. - */ - @Mapping(target = "artifactId", source = "artifactId", qualifiedByName = "emptyToNull") - @Mapping(target = "name", source = "name", qualifiedByName = "emptyToNull") - @Mapping(target = "description", source = "description", qualifiedByName = "emptyToNull") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - @Mapping(target = "extensions", source = "extensions", qualifiedByName = "emptyListToNull") - Artifact fromProto(io.a2a.grpc.Artifact proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java deleted file mode 100644 index 1e50f6d3d..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthenticationInfoMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.a2a.grpc.mapper; - - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.AuthenticationInfo} and {@link io.a2a.grpc.AuthenticationInfo}. - *

    - * Maps between domain AuthenticationInfo (schemes as List of String) and proto AuthenticationInfo (scheme as String). - * The proto scheme field is mapped to/from the first element of the domain schemes list. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface AuthenticationInfoMapper { - - AuthenticationInfoMapper INSTANCE = A2AMappers.getMapper(AuthenticationInfoMapper.class); - - /** - * Converts domain AuthenticationInfo to proto AuthenticationInfo. - * Takes the first scheme from the schemes list. - */ - @Mapping(target = "credentials", source = "credentials", conditionExpression = "java(domain.credentials() != null)") - io.a2a.grpc.AuthenticationInfo toProto(io.a2a.spec.AuthenticationInfo domain); - - /** - * Converts proto AuthenticationInfo to domain AuthenticationInfo. - * Wraps the single scheme in a list. - */ - io.a2a.spec.AuthenticationInfo fromProto(io.a2a.grpc.AuthenticationInfo proto); - - -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java deleted file mode 100644 index d59a3e10a..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/AuthorizationCodeOAuthFlowMapper.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.AuthorizationCodeOAuthFlow} and {@link io.a2a.grpc.AuthorizationCodeOAuthFlow}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface AuthorizationCodeOAuthFlowMapper { - - AuthorizationCodeOAuthFlowMapper INSTANCE = A2AMappers.getMapper(AuthorizationCodeOAuthFlowMapper.class); - - io.a2a.grpc.AuthorizationCodeOAuthFlow toProto(io.a2a.spec.AuthorizationCodeOAuthFlow domain); - - io.a2a.spec.AuthorizationCodeOAuthFlow fromProto(io.a2a.grpc.AuthorizationCodeOAuthFlow proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ClientCredentialsOAuthFlowMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ClientCredentialsOAuthFlowMapper.java deleted file mode 100644 index 6dabe28b6..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ClientCredentialsOAuthFlowMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.ClientCredentialsOAuthFlow} and {@link io.a2a.grpc.ClientCredentialsOAuthFlow}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface ClientCredentialsOAuthFlowMapper { - - ClientCredentialsOAuthFlowMapper INSTANCE = A2AMappers.getMapper(ClientCredentialsOAuthFlowMapper.class); - - io.a2a.grpc.ClientCredentialsOAuthFlow toProto(io.a2a.spec.ClientCredentialsOAuthFlow domain); - - io.a2a.spec.ClientCredentialsOAuthFlow fromProto(io.a2a.grpc.ClientCredentialsOAuthFlow proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java deleted file mode 100644 index d33c04711..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/CreateTaskPushNotificationConfigMapper.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.grpc.CreateTaskPushNotificationConfigRequest; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.TaskPushNotificationConfig; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * MapStruct mapper for CreateTaskPushNotificationConfigRequest → TaskPushNotificationConfig. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {PushNotificationConfigMapper.class}) -public interface CreateTaskPushNotificationConfigMapper { - - CreateTaskPushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(CreateTaskPushNotificationConfigMapper.class); - - /** - * Converts CreateTaskPushNotificationConfigRequest to domain TaskPushNotificationConfig. - * - * @param request the protobuf CreateTaskPushNotificationConfigRequest - * @return domain TaskPushNotificationConfig - */ - @Mapping(target = "config", expression = "java(mapPushNotificationConfigWithId(request))") - TaskPushNotificationConfig fromProto(CreateTaskPushNotificationConfigRequest request); - - /** - * Converts domain TaskPushNotificationConfig to CreateTaskPushNotificationConfigRequest. - * - * @param config the domain TaskPushNotificationConfig - * @return proto CreateTaskPushNotificationConfigRequest - */ - @Mapping(target = "configId", expression = "java(extractConfigId(config))") - CreateTaskPushNotificationConfigRequest toProto(TaskPushNotificationConfig config); - - /** - * Extracts the config ID from the configuration. - * - * @param config the TaskPushNotificationConfig - * @return the extracted config ID - */ - default String extractConfigId(TaskPushNotificationConfig config) { - return config.config() != null ? config.config().id() : null; - } - - /** - * Maps the protobuf PushNotificationConfig to domain, injecting config_id from request. - * - * @param request the protobuf CreateTaskPushNotificationConfigRequest - * @return domain PushNotificationConfig with config_id injected - */ - default PushNotificationConfig mapPushNotificationConfigWithId(CreateTaskPushNotificationConfigRequest request) { - if (!request.hasConfig()) { - return null; - } - - // Map the proto PushNotificationConfig - PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(request.getConfig()); - - // Override ID with config_id from request - String configId = request.getConfigId(); - if (configId != null && !configId.isEmpty() && !configId.equals(result.id())) { - return new PushNotificationConfig( - result.url(), - result.token(), - result.authentication(), - configId - ); - } - - return result; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java deleted file mode 100644 index 6e30f6eb9..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DeleteTaskPushNotificationConfigParamsMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.grpc.DeleteTaskPushNotificationConfigRequest} and {@link io.a2a.spec.DeleteTaskPushNotificationConfigParams}. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface DeleteTaskPushNotificationConfigParamsMapper { - - DeleteTaskPushNotificationConfigParamsMapper INSTANCE = A2AMappers.getMapper(DeleteTaskPushNotificationConfigParamsMapper.class); - - /** - * Converts proto DeleteTaskPushNotificationConfigRequest to domain DeleteTaskPushNotificationConfigParams. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "id", source = "id") - @Mapping(target = "tenant", source = "tenant") - DeleteTaskPushNotificationConfigParams fromProto(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest proto); - - /** - * Converts domain DeleteTaskPushNotificationConfigParams to proto DeleteTaskPushNotificationConfigRequest. - */ - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "id", source = "id") - @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest toProto(DeleteTaskPushNotificationConfigParams domain); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java deleted file mode 100644 index b9a8cad1b..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/GetTaskPushNotificationConfigParamsMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.grpc.GetTaskPushNotificationConfigRequest} and {@link io.a2a.spec.GetTaskPushNotificationConfigParams}. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface GetTaskPushNotificationConfigParamsMapper { - - GetTaskPushNotificationConfigParamsMapper INSTANCE = A2AMappers.getMapper(GetTaskPushNotificationConfigParamsMapper.class); - - /** - * Converts proto GetTaskPushNotificationConfigRequest to domain GetTaskPushNotificationConfigParams. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "id", source = "id") - @Mapping(target = "tenant", source = "tenant") - GetTaskPushNotificationConfigParams fromProto(io.a2a.grpc.GetTaskPushNotificationConfigRequest proto); - - /** - * Converts domain GetTaskPushNotificationConfigParams to proto GetTaskPushNotificationConfigRequest. - */ - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") - @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.GetTaskPushNotificationConfigRequest toProto(GetTaskPushNotificationConfigParams domain); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/HTTPAuthSecuritySchemeMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/HTTPAuthSecuritySchemeMapper.java deleted file mode 100644 index 4953635a1..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/HTTPAuthSecuritySchemeMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.HTTPAuthSecurityScheme} and {@link io.a2a.grpc.HTTPAuthSecurityScheme}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface HTTPAuthSecuritySchemeMapper { - - HTTPAuthSecuritySchemeMapper INSTANCE = A2AMappers.getMapper(HTTPAuthSecuritySchemeMapper.class); - - @Mapping(target = "bearerFormat", source = "bearerFormat", conditionExpression = "java(domain.bearerFormat() != null)") - @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - io.a2a.grpc.HTTPAuthSecurityScheme toProto(io.a2a.spec.HTTPAuthSecurityScheme domain); - - default io.a2a.spec.HTTPAuthSecurityScheme fromProto(io.a2a.grpc.HTTPAuthSecurityScheme proto) { - if (proto == null) { - return null; - } - - String bearerFormat = proto.getBearerFormat().isEmpty() ? null : proto.getBearerFormat(); - String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - - return new io.a2a.spec.HTTPAuthSecurityScheme(bearerFormat, proto.getScheme(), description); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java deleted file mode 100644 index f54ba28d2..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTaskPushNotificationConfigParamsMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.grpc.ListTaskPushNotificationConfigRequest} and {@link io.a2a.spec.ListTaskPushNotificationConfigParams}. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface ListTaskPushNotificationConfigParamsMapper { - - ListTaskPushNotificationConfigParamsMapper INSTANCE = A2AMappers.getMapper(ListTaskPushNotificationConfigParamsMapper.class); - - /** - * Converts proto ListTaskPushNotificationConfigRequest to domain ListTaskPushNotificationConfigParams. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "taskId") - @Mapping(target = "tenant", source = "tenant") - ListTaskPushNotificationConfigParams fromProto(io.a2a.grpc.ListTaskPushNotificationConfigRequest proto); - - /** - * Converts domain ListTaskPushNotificationConfigParams to proto ListTaskPushNotificationConfigRequest. - */ - @Mapping(target = "taskId", source = "id") - @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.ListTaskPushNotificationConfigRequest toProto(ListTaskPushNotificationConfigParams domain); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java deleted file mode 100644 index 06d4c2dd4..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksParamsMapper.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.grpc.ListTasksRequest; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * MapStruct mapper for ListTasksParams ↔ ListTasksRequest conversions. - *

    - * Handles the conversion between domain ListTasksParams and protobuf ListTasksRequest, - * with special handling for optional fields and timestamp conversions. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {TaskStateMapper.class, A2ACommonFieldMapper.class}) -public interface ListTasksParamsMapper { - - ListTasksParamsMapper INSTANCE = A2AMappers.getMapper(ListTasksParamsMapper.class); - - /** - * Converts domain ListTasksParams to protobuf ListTasksRequest. - * - * @param params the domain ListTasksParams - * @return protobuf ListTasksRequest - */ - @Mapping(target = "contextId", source = "contextId", conditionExpression = "java(params.contextId() != null)") - @Mapping(target = "status", source = "status", conditionExpression = "java(params.status() != null)") - @Mapping(target = "pageSize", source = "pageSize", conditionExpression = "java(params.pageSize() != null)") - @Mapping(target = "pageToken", source = "pageToken", conditionExpression = "java(params.pageToken() != null)") - @Mapping(target = "historyLength", source = "historyLength", conditionExpression = "java(params.historyLength() != null)") - @Mapping(target = "statusTimestampAfter", source = "statusTimestampAfter", qualifiedByName = "instantToProtoTimestamp") - @Mapping(target = "includeArtifacts", source = "includeArtifacts", conditionExpression = "java(params.includeArtifacts() != null)") - ListTasksRequest toProto(io.a2a.spec.ListTasksParams params); - - /** - * Converts protobuf ListTasksRequest to domain ListTasksParams. - * - * @param request the protobuf ListTasksRequest - * @return domain ListTasksParams - */ - @Mapping(target = "contextId", source = "contextId", qualifiedByName = "emptyToNull") - @Mapping(target = "status", source = "status", qualifiedByName = "taskStateOrNull") - // pageSize: Check if field is set using hasPageSize() to distinguish unset (null) from explicit 0 (validation error) - @Mapping(target = "pageSize", expression = "java(request.hasPageSize() ? request.getPageSize() : null)") - @Mapping(target = "pageToken", source = "pageToken", qualifiedByName = "emptyToNull") - // historyLength: Check if field is set using hasHistoryLength() for consistency with pageSize - @Mapping(target = "historyLength", expression = "java(request.hasHistoryLength() ? request.getHistoryLength() : null)") - @Mapping(target = "statusTimestampAfter", source = "statusTimestampAfter", qualifiedByName = "protoTimestampToInstant") - @Mapping(target = "includeArtifacts", source = "includeArtifacts", qualifiedByName = "falseToNull") - io.a2a.spec.ListTasksParams fromProto(ListTasksRequest request); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java deleted file mode 100644 index 599877002..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link ListTasksResult} and {@link io.a2a.grpc.ListTasksResponse}. - *

    - * Handles conversion with null handling for nextPageToken field. - * Uses ADDER_PREFERRED strategy to avoid ProtocolMessageList instantiation issues. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = org.mapstruct.CollectionMappingStrategy.ADDER_PREFERRED, - uses = {TaskMapper.class}) -public interface ListTasksResultMapper { - - ListTasksResultMapper INSTANCE = A2AMappers.getMapper(ListTasksResultMapper.class); - - /** - * Converts domain ListTasksResult to proto ListTasksResponse. - * Protobuf builders don't accept null, so nextPageToken is conditionally mapped. - */ - @Mapping(target = "nextPageToken", source = "nextPageToken", conditionExpression = "java(domain.nextPageToken() != null)") - io.a2a.grpc.ListTasksResponse toProto(ListTasksResult domain); - - @Mapping(source = "nextPageToken", target = "nextPageToken", conditionExpression = "java(proto.getNextPageToken() != null)") - ListTasksResult fromProto(io.a2a.grpc.ListTasksResponse proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageMapper.java deleted file mode 100644 index 47cf84f03..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageMapper.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.Message; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.Message} and {@link io.a2a.grpc.Message}. - *

    - * Uses ADDER_PREFERRED strategy for List fields (parts, extensions, referenceTaskIds) - * to avoid ProtocolStringList instantiation issues. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {RoleMapper.class, PartMapper.class, A2ACommonFieldMapper.class}) -public interface MessageMapper { - - MessageMapper INSTANCE = A2AMappers.getMapper(MessageMapper.class); - - /** - * Converts domain Message to proto Message. - * Uses CommonFieldMapper for metadata conversion and ADDER_PREFERRED for lists. - */ - @Mapping(target = "messageId", source = "messageId", conditionExpression = "java(domain.messageId() != null)") - @Mapping(target = "contextId", source = "contextId", conditionExpression = "java(domain.contextId() != null)") - @Mapping(target = "taskId", source = "taskId", conditionExpression = "java(domain.taskId() != null)") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.Message toProto(Message domain); - - /** - * Converts proto Message to domain Message. - * Handles empty string → null and Struct conversions via CommonFieldMapper. - * Uses Builder pattern explicitly configured via @BeanMapping. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "messageId", source = "messageId", qualifiedByName = "requireNonEmpty") - @Mapping(target = "contextId", source = "contextId", qualifiedByName = "emptyToNull") - @Mapping(target = "taskId", source = "taskId", qualifiedByName = "emptyToNull") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - @Mapping(target = "extensions", expression = "java(io.a2a.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getExtensionsList()))") - @Mapping(target = "referenceTaskIds", expression = "java(io.a2a.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getReferenceTaskIdsList()))") - Message fromProto(io.a2a.grpc.Message proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java deleted file mode 100644 index d615527d4..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendConfigurationMapper.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.MessageSendConfiguration; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.MessageSendConfiguration} and {@link io.a2a.grpc.SendMessageConfiguration}. - *

    - * Handles bidirectional mapping with null/empty list conversions and push notification config delegation. - * Uses ADDER_PREFERRED strategy to avoid ProtocolStringList instantiation issues. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {PushNotificationConfigMapper.class, A2ACommonFieldMapper.class}) -public interface MessageSendConfigurationMapper { - - MessageSendConfigurationMapper INSTANCE = A2AMappers.getMapper(MessageSendConfigurationMapper.class); - - /** - * Converts domain MessageSendConfiguration to proto SendMessageConfiguration. - */ - @Mapping(target = "pushNotificationConfig", source = "pushNotificationConfig", conditionExpression = "java(domain.pushNotificationConfig() != null)") - io.a2a.grpc.SendMessageConfiguration toProto(MessageSendConfiguration domain); - - /** - * Converts proto SendMessageConfiguration to domain MessageSendConfiguration. - * Uses Builder pattern for record construction. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "acceptedOutputModes", expression = "java(io.a2a.grpc.mapper.A2ACommonFieldMapper.INSTANCE.emptyListToNull(proto.getAcceptedOutputModesList()))") - MessageSendConfiguration fromProto(io.a2a.grpc.SendMessageConfiguration proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java deleted file mode 100644 index 11885ac11..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MessageSendParamsMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.MessageSendParams; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.MessageSendParams} and {@link io.a2a.grpc.SendMessageRequest}. - *

    - * Handles bidirectional mapping with message/request field name difference and Struct conversions. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {MessageMapper.class, MessageSendConfigurationMapper.class, A2ACommonFieldMapper.class}) -public interface MessageSendParamsMapper { - - MessageSendParamsMapper INSTANCE = A2AMappers.getMapper(MessageSendParamsMapper.class); - - /** - * Converts domain MessageSendParams to proto SendMessageRequest. - * Maps domain "message" field to proto "message" field. - */ - @Mapping(target = "configuration", source = "configuration", conditionExpression = "java(domain.configuration() != null)") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.SendMessageRequest toProto(MessageSendParams domain); - - /** - * Converts proto SendMessageRequest to domain MessageSendParams. - * Maps proto "message" field to domain "message" field. - * Uses Builder pattern for record construction. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - MessageSendParams fromProto(io.a2a.grpc.SendMessageRequest proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MutualTLSSecuritySchemeMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/MutualTLSSecuritySchemeMapper.java deleted file mode 100644 index c6155d580..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/MutualTLSSecuritySchemeMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.MutualTLSSecurityScheme} and {@link io.a2a.grpc.MutualTlsSecurityScheme}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface MutualTLSSecuritySchemeMapper { - - MutualTLSSecuritySchemeMapper INSTANCE = A2AMappers.getMapper(MutualTLSSecuritySchemeMapper.class); - - @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - io.a2a.grpc.MutualTlsSecurityScheme toProto(io.a2a.spec.MutualTLSSecurityScheme domain); - - default io.a2a.spec.MutualTLSSecurityScheme fromProto(io.a2a.grpc.MutualTlsSecurityScheme proto) { - if (proto == null) { - return null; - } - - String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - - return new io.a2a.spec.MutualTLSSecurityScheme(description); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuth2SecuritySchemeMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuth2SecuritySchemeMapper.java deleted file mode 100644 index 088cb509d..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuth2SecuritySchemeMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.OAuth2SecurityScheme} and {@link io.a2a.grpc.OAuth2SecurityScheme}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {OAuthFlowsMapper.class}) -public interface OAuth2SecuritySchemeMapper { - - OAuth2SecuritySchemeMapper INSTANCE = A2AMappers.getMapper(OAuth2SecuritySchemeMapper.class); - - @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - @Mapping(target = "oauth2MetadataUrl", source = "oauth2MetadataUrl", conditionExpression = "java(domain.oauth2MetadataUrl() != null)") - io.a2a.grpc.OAuth2SecurityScheme toProto(io.a2a.spec.OAuth2SecurityScheme domain); - - default io.a2a.spec.OAuth2SecurityScheme fromProto(io.a2a.grpc.OAuth2SecurityScheme proto) { - if (proto == null) { - return null; - } - - io.a2a.spec.OAuthFlows flows = OAuthFlowsMapper.INSTANCE.fromProto(proto.getFlows()); - String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - String oauth2MetadataUrl = proto.getOauth2MetadataUrl().isEmpty() ? null : proto.getOauth2MetadataUrl(); - - return new io.a2a.spec.OAuth2SecurityScheme(flows, description, oauth2MetadataUrl); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java deleted file mode 100644 index 66894d49a..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OAuthFlowsMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.OAuthFlows} and {@link io.a2a.grpc.OAuthFlows}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = { - AuthorizationCodeOAuthFlowMapper.class, - ClientCredentialsOAuthFlowMapper.class - }) -public interface OAuthFlowsMapper { - - OAuthFlowsMapper INSTANCE = A2AMappers.getMapper(OAuthFlowsMapper.class); - - @Mapping(target = "implicit", ignore = true) - @Mapping(target = "password", ignore = true) - io.a2a.grpc.OAuthFlows toProto(io.a2a.spec.OAuthFlows domain); - - io.a2a.spec.OAuthFlows fromProto(io.a2a.grpc.OAuthFlows proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java deleted file mode 100644 index da1dd2d6b..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/OpenIdConnectSecuritySchemeMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.OpenIdConnectSecurityScheme} and {@link io.a2a.grpc.OpenIdConnectSecurityScheme}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface OpenIdConnectSecuritySchemeMapper { - - OpenIdConnectSecuritySchemeMapper INSTANCE = A2AMappers.getMapper(OpenIdConnectSecuritySchemeMapper.class); - - @Mapping(target = "description", source = "description", conditionExpression = "java(domain.description() != null)") - io.a2a.grpc.OpenIdConnectSecurityScheme toProto(io.a2a.spec.OpenIdConnectSecurityScheme domain); - - default io.a2a.spec.OpenIdConnectSecurityScheme fromProto(io.a2a.grpc.OpenIdConnectSecurityScheme proto) { - if (proto == null) { - return null; - } - - String description = proto.getDescription().isEmpty() ? null : proto.getDescription(); - - return new io.a2a.spec.OpenIdConnectSecurityScheme(proto.getOpenIdConnectUrl(), description); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java deleted file mode 100644 index 8704f4699..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PartMapper.java +++ /dev/null @@ -1,116 +0,0 @@ -package io.a2a.grpc.mapper; - -import java.util.Base64; - -import com.google.protobuf.ByteString; -import com.google.protobuf.Value; -import io.a2a.spec.DataPart; -import io.a2a.spec.FileContent; -import io.a2a.spec.FilePart; -import io.a2a.spec.FileWithBytes; -import io.a2a.spec.FileWithUri; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import java.util.Map; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.Part} and {@link io.a2a.grpc.Part}. - *

    - * Handles polymorphic Part conversion using the proto's oneof content field: - *

      - *
    • TextPart - maps to Part.text
    • - *
    • FilePart(FileWithBytes) - maps to Part.raw + Part.filename + Part.media_type
    • - *
    • FilePart(FileWithUri) - maps to Part.url + Part.filename + Part.media_type
    • - *
    • DataPart - maps to Part.data (google.protobuf.Value containing any JSON value: object, array, primitive, or null)
    • - *
    - *

    - * Manual Implementation Required: Must use manual instanceof dispatch to handle protobuf oneof pattern, - * as MapStruct's @SubclassMapping maps to different target types, not different fields of the same type. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {A2ACommonFieldMapper.class}) -public interface PartMapper { - - PartMapper INSTANCE = A2AMappers.getMapper(PartMapper.class); - - /** - * Converts domain Part to proto Part. - * Handles TextPart, FilePart (FileWithBytes and FileWithUri), and DataPart polymorphism. - */ - default io.a2a.grpc.Part toProto(Part domain) { - if (domain == null) { - return null; - } - - io.a2a.grpc.Part.Builder builder = io.a2a.grpc.Part.newBuilder(); - - if (domain instanceof TextPart textPart) { - builder.setText(textPart.text()); - builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(textPart.metadata())); - } else if (domain instanceof FilePart filePart) { - FileContent fileContent = filePart.file(); - - if (fileContent instanceof FileWithBytes fileWithBytes) { - // Map to raw (bytes), filename, and media_type - builder.setRaw(ByteString.copyFrom(Base64.getDecoder().decode(fileWithBytes.bytes()))); - if (fileWithBytes.name() != null) { - builder.setFilename(fileWithBytes.name()); - } - if (fileWithBytes.mimeType() != null) { - builder.setMediaType(fileWithBytes.mimeType()); - } - } else if (fileContent instanceof FileWithUri fileWithUri) { - // Map to url, filename, and media_type - builder.setUrl(fileWithUri.uri()); - if (fileWithUri.name() != null) { - builder.setFilename(fileWithUri.name()); - } - if (fileWithUri.mimeType() != null) { - builder.setMediaType(fileWithUri.mimeType()); - } - } - builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(filePart.metadata())); - } else if (domain instanceof DataPart dataPart) { - // Map data to google.protobuf.Value (supports object, array, primitive, or null) - Value dataValue = A2ACommonFieldMapper.INSTANCE.objectToValue(dataPart.data()); - builder.setData(dataValue); - builder.setMetadata(A2ACommonFieldMapper.INSTANCE.metadataToProto(dataPart.metadata())); - } - - return builder.build(); - } - - /** - * Converts proto Part to domain Part. - * Reconstructs TextPart, FilePart, or DataPart based on oneof content field. - */ - default Part fromProto(io.a2a.grpc.Part proto) { - if (proto == null) { - return null; - } - Map metadata = A2ACommonFieldMapper.INSTANCE.metadataFromProto(proto.getMetadata()); - if (proto.hasText()) { - return new TextPart(proto.getText(), metadata); - } else if (proto.hasRaw()) { - // raw bytes → FilePart(FileWithBytes) - String bytes = Base64.getEncoder().encodeToString(proto.getRaw().toByteArray()); - String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); - String name = proto.getFilename().isEmpty() ? null : proto.getFilename(); - return new FilePart(new FileWithBytes(mimeType, name, bytes), metadata); - } else if (proto.hasUrl()) { - // url → FilePart(FileWithUri) - String uri = proto.getUrl(); - String mimeType = proto.getMediaType().isEmpty() ? null : proto.getMediaType(); - String name = proto.getFilename().isEmpty() ? null : proto.getFilename(); - return new FilePart(new FileWithUri(mimeType, name, uri), metadata); - } else if (proto.hasData()) { - // data (google.protobuf.Value containing any JSON value) → DataPart - Value dataValue = proto.getData(); - Object data = A2ACommonFieldMapper.INSTANCE.valueToObject(dataValue); - return new DataPart(data, metadata); - } - - throw new InvalidRequestError(); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/PushNotificationConfigMapper.java deleted file mode 100644 index 18ae705d5..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/PushNotificationConfigMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.PushNotificationConfig} and {@link io.a2a.grpc.PushNotificationConfig}. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {AuthenticationInfoMapper.class, A2ACommonFieldMapper.class}) -public interface PushNotificationConfigMapper { - - PushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(PushNotificationConfigMapper.class); - - @Mapping(target = "url", source = "url", conditionExpression = "java(domain.url() != null)") - @Mapping(target = "token", source = "token", conditionExpression = "java(domain.token() != null)") - @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(domain.authentication() != null)") - @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") - io.a2a.grpc.PushNotificationConfig toProto(io.a2a.spec.PushNotificationConfig domain); - - /** - * Converts proto PushNotificationConfig to domain. - * Uses declarative mappings with empty string → null conversion via CommonFieldMapper. - */ - @Mapping(target = "token", source = "token", qualifiedByName = "emptyToNull") - @Mapping(target = "id", source = "id", qualifiedByName = "emptyToNull") - @Mapping(target = "authentication", source = "authentication", conditionExpression = "java(proto.hasAuthentication())") - io.a2a.spec.PushNotificationConfig fromProto(io.a2a.grpc.PushNotificationConfig proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ResourceNameParser.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ResourceNameParser.java deleted file mode 100644 index ba7303a74..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ResourceNameParser.java +++ /dev/null @@ -1,106 +0,0 @@ -package io.a2a.grpc.mapper; - -/** - * Utility class for parsing gRPC resource names. - *

    - * Provides methods to extract IDs and components from resource name strings - * following the pattern: "tasks/{taskId}/pushNotificationConfigs/{configId}" - */ -public class ResourceNameParser { - - /** - * Extracts the task ID from a simple resource name like "tasks/{taskId}". - * - * @param resourceName the resource name (e.g., "tasks/abc123") - * @return the extracted task ID - */ - public static String extractTaskId(String resourceName) { - return resourceName.substring(resourceName.lastIndexOf('/') + 1); - } - - /** - * Define the task name form its taskId as in "tasks/{taskId}". - * - * @param taskId the taskId - * @return the task name - */ - public static String defineTaskName(String taskId) { - return "tasks/" + taskId; - } - - /** - * Parses a task push notification config resource name and extracts taskId and configId. - *

    - * Expected format: "tasks/{taskId}/pushNotificationConfigs/{configId}" - * - * @param resourceName the resource name to parse - * @return array with [taskId, configId] - * @throws IllegalArgumentException if the format is invalid - */ - public static String[] parseTaskPushNotificationConfigName(String resourceName) { - String[] parts = resourceName.split("/"); - if (parts.length < 4) { - throw new IllegalArgumentException("Invalid name format for TaskPushNotificationConfig: " + resourceName); - } - return new String[]{parts[1], parts[3]}; - } - - /** - * Parses a get task push notification config request name and extracts taskId and configId. - *

    - * Expected formats: - * - "tasks/{taskId}" (returns taskId for both values) - * - "tasks/{taskId}/pushNotificationConfigs/{configId}" - * - * @param resourceName the resource name to parse - * @return array with [taskId, configId] - * @throws IllegalArgumentException if the format is invalid - */ - public static String[] parseGetTaskPushNotificationConfigName(String resourceName) { - String[] parts = resourceName.split("/"); - String taskId = parts[1]; - String configId; - - if (parts.length == 2) { - // "tasks/{taskId}" - use taskId as configId - configId = taskId; - } else if (parts.length < 4) { - throw new IllegalArgumentException("Invalid name format for GetTaskPushNotificationConfigRequest: " + resourceName); - } else { - // "tasks/{taskId}/pushNotificationConfigs/{configId}" - configId = parts[3]; - } - - return new String[]{taskId, configId}; - } - public static String defineGetTaskPushNotificationConfigName(String taskId, String configId) { - String name= "tasks/" + taskId ; - if(configId != null && !configId.isBlank()) { - name = name + "/pushNotificationConfigs/" + configId; - } - return name; - } - - /** - * Constructs a task push notification config resource name from task ID and config ID. - *

    - * Format: "tasks/{taskId}/pushNotificationConfigs/{configId}" - * - * @param taskId the task identifier - * @param configId the push notification config identifier - * @return the formatted resource name - */ - public static String defineTaskPushNotificationConfigName(String taskId, String configId) { - return "tasks/" + taskId + "/pushNotificationConfigs/" + configId; - } - - /** - * Extracts the parent ID (task ID) from a parent resource name like "tasks/{taskId}". - * - * @param parentName the parent resource name - * @return the extracted parent ID - */ - public static String extractParentId(String parentName) { - return parentName.substring(parentName.lastIndexOf('/') + 1); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java deleted file mode 100644 index 8ff59552c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/RoleMapper.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.grpc.Role; -import io.a2a.spec.Message; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.Message.Role} and {@link io.a2a.grpc.Role}. - *

    - * Handles enum conversion between domain and protobuf role representations: - *

      - *
    • ROLE_USER (domain) ↔ ROLE_USER (proto)
    • - *
    • ROLE_AGENT (domain) ↔ ROLE_AGENT (proto)
    • - *
    • ROLE_UNSPECIFIED (domain) ↔ ROLE_UNSPECIFIED (proto)
    • - *
    - *

    - * Manual Implementation Required: Uses manual switch statements instead of @ValueMapping - * to avoid mapstruct-spi-protobuf enum strategy initialization issues. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface RoleMapper { - - RoleMapper INSTANCE = A2AMappers.getMapper(RoleMapper.class); - - /** - * Converts domain Role to proto Role. - */ - default io.a2a.grpc.Role toProto(Message.Role domain) { - if (domain == null) { - return io.a2a.grpc.Role.ROLE_UNSPECIFIED; - } - return switch (domain) { - case ROLE_USER -> io.a2a.grpc.Role.ROLE_USER; - case ROLE_AGENT -> io.a2a.grpc.Role.ROLE_AGENT; - case ROLE_UNSPECIFIED -> Role.ROLE_UNSPECIFIED; - }; - } - - /** - * Converts proto Role to domain Role. - */ - default Message.Role fromProto(io.a2a.grpc.Role proto) { - if (proto == null || proto == io.a2a.grpc.Role.ROLE_UNSPECIFIED) { - return null; - } - return switch (proto) { - case ROLE_USER -> Message.Role.ROLE_USER; - case ROLE_AGENT -> Message.Role.ROLE_AGENT; - default -> Message.Role.ROLE_UNSPECIFIED; - }; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java deleted file mode 100644 index 8f9f98fe6..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecurityRequirementMapper.java +++ /dev/null @@ -1,112 +0,0 @@ -package io.a2a.grpc.mapper; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.google.protobuf.ProtocolStringList; -import io.a2a.grpc.StringList; -import org.mapstruct.Mapper; - -/** - * Mapper between domain security requirements and protobuf SecurityRequirement messages. - *

    - * Domain representation: {@code List} where each SecurityRequirement contains - * a schemes map with scheme names as keys and scopes as values. - *

    - * Proto representation: {@code repeated SecurityRequirement} where each SecurityRequirement has - * {@code map schemes}. - *

    - * Example: A security requirement that allows either OAuth2 with read/write scopes OR API Key: - *

    - * Domain: [
    - *   SecurityRequirement{schemes: {"oauth2": ["read", "write"]}},
    - *   SecurityRequirement{schemes: {"apiKey": []}}
    - * ]
    - * Proto: [
    - *   SecurityRequirement{schemes: {"oauth2": StringList{values: ["read", "write"]}}},
    - *   SecurityRequirement{schemes: {"apiKey": StringList{values: []}}}
    - * ]
    - * 
    - *

    - * Manual Implementation Required: Handles complex nested structure ({@code List} ↔ - * {@code repeated SecurityRequirement} with {@code map}) requiring manual iteration and StringList wrapper handling. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface SecurityRequirementMapper { - - SecurityRequirementMapper INSTANCE = A2AMappers.getMapper(SecurityRequirementMapper.class); - - /** - * Converts a single domain SecurityRequirement to a proto SecurityRequirement message. - *

    - * MapStruct will call this method for each element when mapping the list. - * - * @param domainRequirement domain SecurityRequirement with schemes map - * @return SecurityRequirement proto message, or null if input is null - */ - default io.a2a.grpc.SecurityRequirement mapSecurityRequirement(io.a2a.spec.SecurityRequirement domainRequirement) { - if (domainRequirement == null) { - return null; - } - - io.a2a.grpc.SecurityRequirement.Builder securityBuilder = io.a2a.grpc.SecurityRequirement.newBuilder(); - Map> schemes = domainRequirement.schemes(); - if (schemes != null) { - for (Map.Entry> entry : schemes.entrySet()) { - StringList.Builder stringListBuilder = StringList.newBuilder(); - if (entry.getValue() != null) { - stringListBuilder.addAllList(entry.getValue()); - } - securityBuilder.putSchemes(entry.getKey(), stringListBuilder.build()); - } - } - return securityBuilder.build(); - } - - /** - * Converts domain security requirements to proto SecurityRequirement messages. - *

    - * Each SecurityRequirement in the domain list becomes one SecurityRequirement message in proto, - * representing one way to satisfy the security requirements (OR relationship between list items). - * - * @param domainSecurity list of SecurityRequirement domain objects - * @return list of SecurityRequirement proto messages, or null if input is null - */ - default List toProto(List domainSecurity) { - if (domainSecurity == null) { - return null; - } - - List protoList = new ArrayList<>(domainSecurity.size()); - for (io.a2a.spec.SecurityRequirement requirement : domainSecurity) { - protoList.add(mapSecurityRequirement(requirement)); - } - return protoList; - } - - /** - * Converts proto SecurityRequirement messages to domain security requirements. - * - * @param protoSecurity list of SecurityRequirement proto messages - * @return list of SecurityRequirement domain objects, or null if input is null - */ - default List fromProto(List protoSecurity) { - if (protoSecurity == null) { - return null; - } - - List domainList = new ArrayList<>(protoSecurity.size()); - for (io.a2a.grpc.SecurityRequirement security : protoSecurity) { - Map> schemeMap = new LinkedHashMap<>(); - for (Map.Entry entry : security.getSchemesMap().entrySet()) { - ProtocolStringList listList = entry.getValue().getListList(); - List values = new ArrayList<>(listList); - schemeMap.put(entry.getKey(), values); - } - domainList.add(new io.a2a.spec.SecurityRequirement(schemeMap)); - } - return domainList; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecuritySchemeMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecuritySchemeMapper.java deleted file mode 100644 index 723762785..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SecuritySchemeMapper.java +++ /dev/null @@ -1,104 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.APIKeySecurityScheme; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.MutualTLSSecurityScheme; -import io.a2a.spec.OAuth2SecurityScheme; -import io.a2a.spec.OpenIdConnectSecurityScheme; -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.SecurityScheme} and {@link io.a2a.grpc.SecurityScheme}. - *

    - * This mapper handles the polymorphic sealed interface SecurityScheme by using a custom - * default method with switch expression. MapStruct doesn't natively support sealed interfaces - * with protobuf's oneof pattern, so we manually dispatch to the appropriate concrete mapper. - *

    - * Manual Implementation Required: Must use manual instanceof dispatch to handle sealed interface (5 permitted subtypes) - * to protobuf oneof pattern, as MapStruct's @SubclassMapping cannot map different source types to different fields of the same target type. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = { - APIKeySecuritySchemeMapper.class, - HTTPAuthSecuritySchemeMapper.class, - OAuth2SecuritySchemeMapper.class, - OpenIdConnectSecuritySchemeMapper.class, - MutualTLSSecuritySchemeMapper.class - }) -public interface SecuritySchemeMapper { - - SecuritySchemeMapper INSTANCE = A2AMappers.getMapper(SecuritySchemeMapper.class); - - /** - * Converts a domain SecurityScheme to protobuf SecurityScheme. - *

    - * Uses instanceof checks to handle sealed interface polymorphism, dispatching to the - * appropriate concrete mapper based on the runtime type. This is necessary because - * MapStruct cannot automatically handle sealed interfaces with protobuf oneof fields. - * - * @param domain the domain security scheme (sealed interface) - * @return the protobuf SecurityScheme with the appropriate oneof field set - */ - default io.a2a.grpc.SecurityScheme toProto(io.a2a.spec.SecurityScheme domain) { - if (domain == null) { - return null; - } - - if (domain instanceof APIKeySecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() - .setApiKeySecurityScheme(APIKeySecuritySchemeMapper.INSTANCE.toProto(s)) - .build(); - } else if (domain instanceof HTTPAuthSecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() - .setHttpAuthSecurityScheme(HTTPAuthSecuritySchemeMapper.INSTANCE.toProto(s)) - .build(); - } else if (domain instanceof OAuth2SecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() - .setOauth2SecurityScheme(OAuth2SecuritySchemeMapper.INSTANCE.toProto(s)) - .build(); - } else if (domain instanceof OpenIdConnectSecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() - .setOpenIdConnectSecurityScheme(OpenIdConnectSecuritySchemeMapper.INSTANCE.toProto(s)) - .build(); - } else if (domain instanceof MutualTLSSecurityScheme s) { - return io.a2a.grpc.SecurityScheme.newBuilder() - .setMtlsSecurityScheme(MutualTLSSecuritySchemeMapper.INSTANCE.toProto(s)) - .build(); - } - - throw new IllegalArgumentException("Unknown SecurityScheme type: " + domain.getClass()); - } - - /** - * Converts a protobuf SecurityScheme to domain SecurityScheme. - *

    - * Uses oneof checks to determine which security scheme type is set, dispatching to the - * appropriate concrete mapper. This reverses the toProto conversion by checking which - * oneof field is populated. - * - * @param proto the protobuf SecurityScheme with a oneof field set - * @return the domain security scheme (sealed interface implementation) - */ - default io.a2a.spec.SecurityScheme fromProto(io.a2a.grpc.SecurityScheme proto) { - if (proto == null) { - return null; - } - - return switch (proto.getSchemeCase()) { - case API_KEY_SECURITY_SCHEME -> - APIKeySecuritySchemeMapper.INSTANCE.fromProto(proto.getApiKeySecurityScheme()); - case HTTP_AUTH_SECURITY_SCHEME -> - HTTPAuthSecuritySchemeMapper.INSTANCE.fromProto(proto.getHttpAuthSecurityScheme()); - case OAUTH2_SECURITY_SCHEME -> - OAuth2SecuritySchemeMapper.INSTANCE.fromProto(proto.getOauth2SecurityScheme()); - case OPEN_ID_CONNECT_SECURITY_SCHEME -> - OpenIdConnectSecuritySchemeMapper.INSTANCE.fromProto(proto.getOpenIdConnectSecurityScheme()); - case MTLS_SECURITY_SCHEME -> - MutualTLSSecuritySchemeMapper.INSTANCE.fromProto(proto.getMtlsSecurityScheme()); - case SCHEME_NOT_SET -> - throw new IllegalArgumentException("SecurityScheme oneof field not set"); - }; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java deleted file mode 100644 index 07eacb148..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/StreamResponseMapper.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.StreamingEventKind} and {@link io.a2a.grpc.StreamResponse}. - *

    - * StreamResponse uses a protobuf oneof field to represent polymorphic streaming events. - * StreamingEventKind is a sealed interface with four permitted implementations: - *

      - *
    • {@link Task} - Complete task state
    • - *
    • {@link Message} - Full message
    • - *
    • {@link TaskStatusUpdateEvent} - Status update event
    • - *
    • {@link TaskArtifactUpdateEvent} - Artifact update event
    • - *
    - *

    - * This mapper provides bidirectional conversion using instanceof checks (toProto) - * and switch expressions on the oneof case (fromProto). - */ -@Mapper(config = A2AProtoMapperConfig.class, - uses = {TaskMapper.class, MessageMapper.class, TaskStatusUpdateEventMapper.class, TaskArtifactUpdateEventMapper.class}) -public interface StreamResponseMapper { - - StreamResponseMapper INSTANCE = A2AMappers.getMapper(StreamResponseMapper.class); - - /** - * Converts domain StreamingEventKind to proto StreamResponse. - * Uses instanceof checks to determine which oneof field to set. - * - * @param domain the streaming event kind (Task, Message, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent) - * @return the proto StreamResponse with the appropriate oneof field set - */ - default io.a2a.grpc.StreamResponse toProto(StreamingEventKind domain) { - if (domain == null) { - return null; - } - - return switch (domain.kind()) { - case Task.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setTask(TaskMapper.INSTANCE.toProto((Task) domain)) - .build(); - case Message.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setMessage(MessageMapper.INSTANCE.toProto((Message) domain)) - .build(); - case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setStatusUpdate(TaskStatusUpdateEventMapper.INSTANCE.toProto((TaskStatusUpdateEvent) domain)) - .build(); - case TaskArtifactUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setArtifactUpdate(TaskArtifactUpdateEventMapper.INSTANCE.toProto((TaskArtifactUpdateEvent) domain)) - .build(); - default -> - throw new IllegalArgumentException("Unknown StreamingEventKind type: " + domain.getClass().getName()); - }; - } - - /** - * Converts proto StreamResponse to domain StreamingEventKind. - * Uses switch expression on the oneof case to determine which type to return. - * - * @param proto the proto StreamResponse - * @return the corresponding domain streaming event kind - * @throws IllegalArgumentException if the oneof field is not set - */ - default StreamingEventKind fromProto(io.a2a.grpc.StreamResponse proto) { - if (proto == null) { - return null; - } - - return switch (proto.getPayloadCase()) { - case TASK -> - TaskMapper.INSTANCE.fromProto(proto.getTask()); - case MESSAGE -> - MessageMapper.INSTANCE.fromProto(proto.getMessage()); - case STATUS_UPDATE -> - TaskStatusUpdateEventMapper.INSTANCE.fromProto(proto.getStatusUpdate()); - case ARTIFACT_UPDATE -> - TaskArtifactUpdateEventMapper.INSTANCE.fromProto(proto.getArtifactUpdate()); - case PAYLOAD_NOT_SET -> - throw new IllegalArgumentException("StreamResponse payload oneof field not set"); - }; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java deleted file mode 100644 index c21d1d8a7..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; -import org.mapstruct.Mapper; - -/** - * Mapper between {@link SubscribeToTaskRequest} and {@link io.a2a.grpc.SubscribeToTaskRequest}. - *

    - * The mapping handles the structural difference between domain and proto representations: - *

      - *
    • Domain: Full JSONRPC request with id, jsonrpc, method, and params (TaskIdParams)
    • - *
    • Proto: Simple request with name field in format "tasks/{task_id}"
    • - *
    - *

    - * Note: The domain object is a complete JSONRPC request, while the proto is just the gRPC - * request parameters. The JSONRPC envelope (id, jsonrpc, method) is handled separately - * by the transport layer. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {TaskIdParamsMapper.class}) -public interface SubscribeToTaskRequestMapper { - - SubscribeToTaskRequestMapper INSTANCE = A2AMappers.getMapper(SubscribeToTaskRequestMapper.class); - - /** - * Converts domain SubscribeToTaskRequest to proto SubscribeToTaskRequest. - * Extracts the task ID from params and formats it as "tasks/{task_id}". - * - * @param domain the domain SubscribeToTaskRequest - * @return the proto SubscribeToTaskRequest - */ - default io.a2a.grpc.SubscribeToTaskRequest toProto(SubscribeToTaskRequest domain) { - if (domain == null || domain.getParams() == null || domain.getParams().id() == null) { - return null; - } - return io.a2a.grpc.SubscribeToTaskRequest.newBuilder() - .setId(domain.getParams().id()) - .build(); - } - - /** - * Converts proto SubscribeToTaskRequest to domain SubscribeToTaskRequest. - * Extracts the task ID from the name field and creates a TaskIdParams. - * - * @param proto the proto SubscribeToTaskRequest - * @return the domain SubscribeToTaskRequest - */ - default SubscribeToTaskRequest fromProto(io.a2a.grpc.SubscribeToTaskRequest proto) { - if (proto == null || proto.getId()== null) { - return null; - } - return SubscribeToTaskRequest.builder() - .params(new io.a2a.spec.TaskIdParams(proto.getId())) - .build(); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskArtifactUpdateEventMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskArtifactUpdateEventMapper.java deleted file mode 100644 index 2c52d80d2..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskArtifactUpdateEventMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.TaskArtifactUpdateEvent; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.TaskArtifactUpdateEvent} and {@link io.a2a.grpc.TaskArtifactUpdateEvent}. - *

    - * Now fully declarative using Builder pattern with @BeanMapping. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {ArtifactMapper.class, A2ACommonFieldMapper.class}) -public interface TaskArtifactUpdateEventMapper { - - TaskArtifactUpdateEventMapper INSTANCE = A2AMappers.getMapper(TaskArtifactUpdateEventMapper.class); - - /** - * Converts domain TaskArtifactUpdateEvent to proto. - * Uses declarative mapping with CommonFieldMapper for metadata conversion. - */ - @Mapping(target = "append", source = "append", conditionExpression = "java(domain.append() != null)") - @Mapping(target = "lastChunk", source = "lastChunk", conditionExpression = "java(domain.lastChunk() != null)") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.TaskArtifactUpdateEvent toProto(TaskArtifactUpdateEvent domain); - - /** - * Converts proto TaskArtifactUpdateEvent to domain. - * Now fully declarative using Builder pattern configured via @BeanMapping. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - TaskArtifactUpdateEvent fromProto(io.a2a.grpc.TaskArtifactUpdateEvent proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java deleted file mode 100644 index 70595b50e..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskIdParamsMapper.java +++ /dev/null @@ -1,52 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.TaskIdParams; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper for {@link io.a2a.spec.TaskIdParams} from various gRPC request types. - *

    - * Extracts task ID from resource name format "tasks/{id}" using {@link ResourceNameParser}. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface TaskIdParamsMapper { - - TaskIdParamsMapper INSTANCE = A2AMappers.getMapper(TaskIdParamsMapper.class); - - /** - * Converts proto CancelTaskRequest to domain TaskIdParams. - * Extracts task ID from the resource name. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "id") - TaskIdParams fromProtoCancelTaskRequest(io.a2a.grpc.CancelTaskRequest proto); - - /** - * Converts proto CancelTaskRequest to domain TaskIdParams. - * Extracts task ID from the resource name. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "id") - io.a2a.grpc.CancelTaskRequest toProtoCancelTaskRequest(TaskIdParams domain); - - - /** - * Converts proto SubscribeToTaskRequest to domain TaskIdParams. - * Extracts task ID from the resource name. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "id") - @Mapping(target = "tenant", source = "tenant") - TaskIdParams fromProtoSubscribeToTaskRequest(io.a2a.grpc.SubscribeToTaskRequest proto); - - /** - * Converts domain TaskIdParams to proto SubscribeToTaskRequest. - * Creates resource name from task ID. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "id") - io.a2a.grpc.SubscribeToTaskRequest toProtoSubscribeToTaskRequest(TaskIdParams domain); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskMapper.java deleted file mode 100644 index 20ece6064..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskMapper.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.Task; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.CollectionMappingStrategy; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.Task} and {@link io.a2a.grpc.Task}. - *

    - * Uses ADDER_PREFERRED strategy for List fields (artifacts, history) - * to use addAllArtifacts() and addAllHistory() methods. - */ -@Mapper(config = A2AProtoMapperConfig.class, - collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, - uses = {TaskStatusMapper.class, ArtifactMapper.class, MessageMapper.class, A2ACommonFieldMapper.class}) -public interface TaskMapper { - - TaskMapper INSTANCE = A2AMappers.getMapper(TaskMapper.class); - - /** - * Converts domain Task to proto Task. - * Uses CommonFieldMapper for metadata conversion and ADDER_PREFERRED for lists. - */ - @Mapping(target = "id", source = "id", conditionExpression = "java(domain.id() != null)") - @Mapping(target = "contextId", source = "contextId", conditionExpression = "java(domain.contextId() != null)") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.Task toProto(Task domain); - - /** - * Converts proto Task to domain Task. - * Handles empty string → null and Struct conversions via CommonFieldMapper. - * Uses Builder pattern explicitly configured via @BeanMapping. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "id", qualifiedByName = "emptyToNull") - @Mapping(target = "contextId", source = "contextId", qualifiedByName = "emptyToNull") - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataFromProto") - Task fromProto(io.a2a.grpc.Task proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java deleted file mode 100644 index 5e3a6e669..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskPushNotificationConfigMapper.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.TaskPushNotificationConfig; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * MapStruct mapper for TaskPushNotificationConfig. - *

    - * Maps between domain TaskPushNotificationConfig and proto TaskPushNotificationConfig. - * The proto now has direct task_id and id fields instead of a resource name. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {PushNotificationConfigMapper.class}) -public interface TaskPushNotificationConfigMapper { - - TaskPushNotificationConfigMapper INSTANCE = A2AMappers.getMapper(TaskPushNotificationConfigMapper.class); - - /** - * Converts domain TaskPushNotificationConfig to protobuf TaskPushNotificationConfig. - * - * @param domain the domain TaskPushNotificationConfig - * @return protobuf TaskPushNotificationConfig - */ - @Mapping(target = "id", expression = "java(extractId(domain))") - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "pushNotificationConfig", source = "config") - @Mapping(target = "tenant", source = "tenant", conditionExpression = "java(domain.tenant() != null)") - io.a2a.grpc.TaskPushNotificationConfig toProto(TaskPushNotificationConfig domain); - - /** - * Converts protobuf TaskPushNotificationConfig to domain TaskPushNotificationConfig. - * - * @param proto the protobuf TaskPushNotificationConfig - * @return domain TaskPushNotificationConfig - */ - @Mapping(target = "taskId", source = "taskId") - @Mapping(target = "config", expression = "java(mapPushNotificationConfigWithId(proto))") - @Mapping(target = "tenant", expression = "java(proto.getTenant().isEmpty() ? null : proto.getTenant())") - TaskPushNotificationConfig fromProto(io.a2a.grpc.TaskPushNotificationConfig proto); - - /** - * Extracts the config ID from the PushNotificationConfig. - * - * @param config the domain TaskPushNotificationConfig - * @return the config ID - */ - default String extractId(TaskPushNotificationConfig config) { - return config.config()!= null ? config.config().id() : null; - } - - /** - * Maps the protobuf PushNotificationConfig to domain, ensuring the ID matches the proto's id field. - * - * @param proto the protobuf TaskPushNotificationConfig - * @return domain PushNotificationConfig with correct ID - */ - default PushNotificationConfig mapPushNotificationConfigWithId(io.a2a.grpc.TaskPushNotificationConfig proto) { - if (!proto.hasPushNotificationConfig() || - proto.getPushNotificationConfig().equals(io.a2a.grpc.PushNotificationConfig.getDefaultInstance())) { - return null; - } - - // Map the proto PushNotificationConfig - PushNotificationConfig result = PushNotificationConfigMapper.INSTANCE.fromProto(proto.getPushNotificationConfig()); - - // Override ID with the id from TaskPushNotificationConfig if they differ - String configId = proto.getId(); - if (configId != null && !configId.isEmpty() && !configId.equals(result.id())) { - return new PushNotificationConfig(result.url(), result.token(), result.authentication(), configId); - } - - return result; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java deleted file mode 100644 index 4d13ff514..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskQueryParamsMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.TaskQueryParams; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.grpc.GetTaskRequest} and {@link io.a2a.spec.TaskQueryParams}. - *

    - * Extracts task ID from resource name format "tasks/{id}" using {@link ResourceNameParser}. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface TaskQueryParamsMapper { - - TaskQueryParamsMapper INSTANCE = A2AMappers.getMapper(TaskQueryParamsMapper.class); - - /** - * Converts proto GetTaskRequest to domain TaskQueryParams. - * Extracts task ID from the resource name. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "id") - @Mapping(target = "historyLength", source = "historyLength") - TaskQueryParams fromProto(io.a2a.grpc.GetTaskRequest proto); - - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "id", source = "id") - @Mapping(target = "historyLength", source = "historyLength") - @Mapping(target = "tenant", source = "tenant") - io.a2a.grpc.GetTaskRequest toProto(TaskQueryParams domain); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java deleted file mode 100644 index dcafce7ee..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStateMapper.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.a2a.grpc.mapper; - -import org.mapstruct.Mapper; - -/** - * Mapper between {@link io.a2a.spec.TaskState} and {@link io.a2a.grpc.TaskState}. - *

    - * Handles the conversion between domain TaskState enum (with string-based wire format) - * and protobuf TaskState enum (with integer-based wire format and TASK_STATE_ prefix). - *

    - * Note: Proto uses CANCELLED spelling while domain uses CANCELED. - *

    - * Manual Implementation Required: Uses manual switch statements instead of @ValueMapping - * to avoid mapstruct-spi-protobuf enum strategy initialization issues. - */ -@Mapper(config = A2AProtoMapperConfig.class) -public interface TaskStateMapper { - - TaskStateMapper INSTANCE = A2AMappers.getMapper(TaskStateMapper.class); - - /** - * Converts domain TaskState to proto TaskState. - * - * @param domain the domain task state - * @return the proto task state, or TASK_STATE_UNSPECIFIED if input is null - */ - default io.a2a.grpc.TaskState toProto(io.a2a.spec.TaskState domain) { - if (domain == null) { - return io.a2a.grpc.TaskState.TASK_STATE_UNSPECIFIED; - } - - return switch (domain) { - case TASK_STATE_SUBMITTED -> io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED; - case TASK_STATE_WORKING -> io.a2a.grpc.TaskState.TASK_STATE_WORKING; - case TASK_STATE_INPUT_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_INPUT_REQUIRED; - case TASK_STATE_AUTH_REQUIRED -> io.a2a.grpc.TaskState.TASK_STATE_AUTH_REQUIRED; - case TASK_STATE_COMPLETED -> io.a2a.grpc.TaskState.TASK_STATE_COMPLETED; - case TASK_STATE_CANCELED -> io.a2a.grpc.TaskState.TASK_STATE_CANCELED; - case TASK_STATE_FAILED -> io.a2a.grpc.TaskState.TASK_STATE_FAILED; - case TASK_STATE_REJECTED -> io.a2a.grpc.TaskState.TASK_STATE_REJECTED; - case UNRECOGNIZED -> io.a2a.grpc.TaskState.UNRECOGNIZED; - }; - } - - /** - * Converts proto TaskState to domain TaskState. - * - * @param proto the proto task state - * @return the domain task state, or UNKNOWN if input is null or unrecognized - */ - default io.a2a.spec.TaskState fromProto(io.a2a.grpc.TaskState proto) { - if (proto == null) { - return io.a2a.spec.TaskState.UNRECOGNIZED; - } - - return switch (proto) { - case TASK_STATE_SUBMITTED -> io.a2a.spec.TaskState.TASK_STATE_SUBMITTED; - case TASK_STATE_WORKING -> io.a2a.spec.TaskState.TASK_STATE_WORKING; - case TASK_STATE_INPUT_REQUIRED -> io.a2a.spec.TaskState.TASK_STATE_INPUT_REQUIRED; - case TASK_STATE_AUTH_REQUIRED -> io.a2a.spec.TaskState.TASK_STATE_AUTH_REQUIRED; - case TASK_STATE_COMPLETED -> io.a2a.spec.TaskState.TASK_STATE_COMPLETED; - case TASK_STATE_CANCELED -> io.a2a.spec.TaskState.TASK_STATE_CANCELED; - case TASK_STATE_FAILED -> io.a2a.spec.TaskState.TASK_STATE_FAILED; - case TASK_STATE_REJECTED -> io.a2a.spec.TaskState.TASK_STATE_REJECTED; - case TASK_STATE_UNSPECIFIED, UNRECOGNIZED -> io.a2a.spec.TaskState.UNRECOGNIZED; - }; - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusMapper.java deleted file mode 100644 index f6c32c81c..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusMapper.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.TaskStatus; -import org.mapstruct.BeanMapping; -import org.mapstruct.Builder; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.TaskStatus} and {@link io.a2a.grpc.TaskStatus}. - *

    - * Handles conversion of task status including state, optional message, and timestamp. - * Uses TaskStateMapper for state conversion, MessageMapper for message conversion, - * and CommonFieldMapper for timestamp conversion. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {TaskStateMapper.class, MessageMapper.class, A2ACommonFieldMapper.class}) -public interface TaskStatusMapper { - - TaskStatusMapper INSTANCE = A2AMappers.getMapper(TaskStatusMapper.class); - - /** - * Converts domain TaskStatus to proto TaskStatus. - * Uses MessageMapper for message and CommonFieldMapper for timestamp conversion. - */ - @Mapping(target = "state", source = "state", conditionExpression = "java(domain.state() != null)") - @Mapping(target = "message", source = "message", conditionExpression = "java(domain.message() != null)") - @Mapping(target = "timestamp", source = "timestamp", qualifiedByName = "offsetDateTimeToProtoTimestamp") - io.a2a.grpc.TaskStatus toProto(TaskStatus domain); - - /** - * Converts proto TaskStatus to domain TaskStatus. - * Uses MessageMapper for message and CommonFieldMapper for timestamp conversion. - */ - @BeanMapping(builder = @Builder(buildMethod = "build")) - @Mapping(target = "timestamp", source = "timestamp", qualifiedByName = "protoTimestampToOffsetDateTime") - TaskStatus fromProto(io.a2a.grpc.TaskStatus proto); -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java deleted file mode 100644 index f8ced3ecf..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/TaskStatusUpdateEventMapper.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.a2a.grpc.mapper; - -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; - -/** - * Mapper between {@link io.a2a.spec.TaskStatusUpdateEvent} and {@link io.a2a.grpc.TaskStatusUpdateEvent}. - *

    - * Now fully declarative using Builder pattern with @BeanMapping. - * Builder's isFinal() method handles the Java "final" keyword mapping. - */ -@Mapper(config = A2AProtoMapperConfig.class, uses = {TaskStatusMapper.class, A2ACommonFieldMapper.class}) -public interface TaskStatusUpdateEventMapper { - - TaskStatusUpdateEventMapper INSTANCE = A2AMappers.getMapper(TaskStatusUpdateEventMapper.class); - - /** - * Converts domain TaskStatusUpdateEvent to proto. - * Uses declarative mapping with CommonFieldMapper for metadata conversion. - * Note: isFinal field is ignored as it has been removed from the proto (field 4 is reserved). - */ - @Mapping(target = "metadata", source = "metadata", qualifiedByName = "metadataToProto") - io.a2a.grpc.TaskStatusUpdateEvent toProto(TaskStatusUpdateEvent domain); - - /** - * Converts proto TaskStatusUpdateEvent to domain. - * Note: isFinal is derived from status.state().isFinal() since the field has been removed from the proto (field 4 is reserved). - */ - default TaskStatusUpdateEvent fromProto(io.a2a.grpc.TaskStatusUpdateEvent proto) { - if (proto == null) { - return null; - } - TaskStatus status = TaskStatusMapper.INSTANCE.fromProto(proto.getStatus()); - return new TaskStatusUpdateEvent( - proto.getTaskId(), - status, - proto.getContextId(), - status != null && status.state() != null && status.state().isFinal(), - A2ACommonFieldMapper.INSTANCE.metadataFromProto(proto.getMetadata()) - ); - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java deleted file mode 100644 index 1480ac42a..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java +++ /dev/null @@ -1,640 +0,0 @@ -package io.a2a.grpc.utils; - -import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED_ERROR; -import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.VERSION_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.Strictness; -import com.google.gson.stream.JsonWriter; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.util.JsonFormat; -import io.a2a.grpc.StreamResponse; -import io.a2a.jsonrpc.common.json.IdJsonMappingException; -import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; -import io.a2a.jsonrpc.common.json.JsonMappingException; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.MethodNotFoundJsonMappingException; -import io.a2a.jsonrpc.common.wrappers.A2AMessage; -import io.a2a.jsonrpc.common.wrappers.A2ARequest; -import io.a2a.jsonrpc.common.wrappers.A2AResponse; -import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; -import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; -import io.a2a.spec.A2AError; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; -import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; - -/** - * Utilities for converting between JSON-RPC 2.0 messages and Protocol Buffer objects. - *

    - * This class provides a unified strategy for handling JSON-RPC requests and responses in the A2A SDK - * by bridging the JSON-RPC transport layer with Protocol Buffer-based internal representations. - * - *

    Conversion Strategy

    - * The conversion process follows a two-step approach: - *
      - *
    1. JSON → Proto: JSON-RPC messages are parsed using Gson, then converted to Protocol Buffer - * objects using Google's {@link JsonFormat} parser. This ensures consistent handling of field names, - * types, and nested structures according to the proto3 specification.
    2. - *
    3. Proto → Spec: Protocol Buffer objects are converted to A2A spec objects using - * {@link ProtoUtils.FromProto} converters, which handle type mappings and create immutable - * spec-compliant Java objects.
    4. - *
    - * - *

    Request Processing Flow

    - *
    - * Incoming JSON-RPC Request
    - *   ↓ parseRequestBody(String)
    - * Validate version, id, method
    - *   ↓ parseMethodRequest()
    - * Parse params → Proto Builder
    - *   ↓ ProtoUtils.FromProto.*
    - * Create JSONRPCRequest<?> with spec objects
    - * 
    - * - *

    Response Processing Flow

    - *
    - * Incoming JSON-RPC Response
    - *   ↓ parseResponseBody(String, String)
    - * Validate version, id, check for errors
    - *   ↓ Parse result/error
    - * Proto Builder → spec objects
    - *   ↓ ProtoUtils.FromProto.*
    - * Create JSONRPCResponse<?> with result or error
    - * 
    - * - *

    Serialization Flow

    - *
    - * Proto MessageOrBuilder
    - *   ↓ JsonFormat.printer()
    - * Proto JSON string
    - *   ↓ Gson JsonWriter
    - * Complete JSON-RPC envelope
    - * 
    - * - *

    Error Handling

    - * The class provides detailed error messages for common failure scenarios: - *
      - *
    • Missing/invalid method: Returns {@link MethodNotFoundError} with the invalid method name
    • - *
    • Invalid parameters: Returns {@link InvalidParamsError} with proto parsing details
    • - *
    • Protocol version mismatch: Returns {@link InvalidRequestError} with version info
    • - *
    • Missing/invalid id: Returns {@link InvalidRequestError} with id validation details
    • - *
    - * - *

    Thread Safety

    - * This class is thread-safe. All methods are stateless and use immutable shared resources - * ({@link Gson} instance is thread-safe, proto builders are created per-invocation). - * - *

    Usage Example

    - *
    {@code
    - * // Parse incoming JSON-RPC request
    - * String jsonRequest = """
    - *     {"jsonrpc":"2.0","id":1,"method":"tasks.get","params":{"name":"tasks/task-123"}}
    - *     """;
    - * JSONRPCRequest request = JSONRPCUtils.parseRequestBody(jsonRequest);
    - *
    - * // Create JSON-RPC request from proto
    - * io.a2a.grpc.GetTaskRequest protoRequest = ...;
    - * String json = JSONRPCUtils.toJsonRPCRequest("req-1", "tasks.get", protoRequest);
    - *
    - * // Create JSON-RPC response from proto
    - * io.a2a.grpc.Task protoTask = ...;
    - * String response = JSONRPCUtils.toJsonRPCResultResponse("req-1", protoTask);
    - * }
    - * - * @see ProtoUtils - * @see A2ARequest - * @see A2AResponse - * @see JSON-RPC 2.0 Specification - */ -public class JSONRPCUtils { - - private static final Logger log = Logger.getLogger(JSONRPCUtils.class.getName()); - private static final Gson GSON = new GsonBuilder() - .setStrictness(Strictness.STRICT) - .create(); - private static final Pattern EXTRACT_WRONG_VALUE = Pattern.compile("Expect (.*) but got: \".*\""); - private static final Pattern EXTRACT_WRONG_TYPE = Pattern.compile("Expected (.*) but found \".*\""); - static final String ERROR_MESSAGE = "Invalid request content: %s. Please verify the request matches the expected schema for this method."; - - public static A2ARequest parseRequestBody(String body, @Nullable String tenant) throws JsonMappingException, JsonProcessingException { - JsonElement jelement = JsonParser.parseString(body); - JsonObject jsonRpc = jelement.getAsJsonObject(); - if (!jsonRpc.has("method")) { - throw new IdJsonMappingException( - "JSON-RPC request missing required 'method' field. Request must include: jsonrpc, id, method, and params.", - getIdIfPossible(jsonRpc)); - } - String version = getAndValidateJsonrpc(jsonRpc); - Object id = getAndValidateId(jsonRpc); - String method = jsonRpc.get("method").getAsString(); - JsonElement paramsNode = jsonRpc.get("params"); - try { - return parseMethodRequest(version, id, method, paramsNode, tenant); - } catch (InvalidParamsError e) { - throw new InvalidParamsJsonMappingException(Utils.defaultIfNull(e.getMessage(), "Invalid parameters"), id); - } - } - - private static A2ARequest parseMethodRequest(String version, Object id, String method, JsonElement paramsNode, @Nullable String tenant) throws InvalidParamsError, MethodNotFoundJsonMappingException, JsonProcessingException { - switch (method) { - case GET_TASK_METHOD -> { - io.a2a.grpc.GetTaskRequest.Builder builder = io.a2a.grpc.GetTaskRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new GetTaskRequest(version, id, ProtoUtils.FromProto.taskQueryParams(builder)); - } - case CANCEL_TASK_METHOD -> { - io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new CancelTaskRequest(version, id, ProtoUtils.FromProto.taskIdParams(builder)); - } - case LIST_TASK_METHOD -> { - io.a2a.grpc.ListTasksRequest.Builder builder = io.a2a.grpc.ListTasksRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new ListTasksRequest(version, id, ProtoUtils.FromProto.listTasksParams(builder)); - } - case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new CreateTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.CreateTaskPushNotificationConfig(builder)); - } - case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new GetTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.getTaskPushNotificationConfigParams(builder)); - } - case SEND_MESSAGE_METHOD -> { - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new SendMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); - } - case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new ListTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigParams(builder)); - } - case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new DeleteTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.deleteTaskPushNotificationConfigParams(builder)); - } - case GET_EXTENDED_AGENT_CARD_METHOD -> { - return new GetExtendedAgentCardRequest(version, id); - } - case SEND_STREAMING_MESSAGE_METHOD -> { - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new SendStreamingMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); - } - case SUBSCRIBE_TO_TASK_METHOD -> { - io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (tenant != null && !tenant.isBlank() && (builder.getTenant() == null || builder.getTenant().isBlank())) { - builder.setTenant(tenant); - } - return new SubscribeToTaskRequest(version, id, ProtoUtils.FromProto.taskIdParams(builder)); - } - default -> - throw new MethodNotFoundJsonMappingException("Unsupported JSON-RPC method: '" + method + "'", id); - } - } - - public static StreamResponse parseResponseEvent(String body) throws JsonMappingException, JsonProcessingException { - JsonElement jelement = JsonParser.parseString(body); - JsonObject jsonRpc = jelement.getAsJsonObject(); - String version = getAndValidateJsonrpc(jsonRpc); - Object id = getAndValidateId(jsonRpc); - JsonElement paramsNode = jsonRpc.get("result"); - if (jsonRpc.has("error")) { - throw processError(jsonRpc.getAsJsonObject("error")); - } - StreamResponse.Builder builder = StreamResponse.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return builder.build(); - } - - public static A2AResponse parseResponseBody(String body, String method) throws JsonMappingException, JsonProcessingException { - JsonElement jelement = JsonParser.parseString(body); - JsonObject jsonRpc = jelement.getAsJsonObject(); - String version = getAndValidateJsonrpc(jsonRpc); - Object id = getAndValidateId(jsonRpc); - JsonElement paramsNode = jsonRpc.get("result"); - if (jsonRpc.has("error")) { - return parseError(jsonRpc.getAsJsonObject("error"), id, method); - } - switch (method) { - case GET_TASK_METHOD -> { - io.a2a.grpc.Task.Builder builder = io.a2a.grpc.Task.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return new GetTaskResponse(id, ProtoUtils.FromProto.task(builder)); - } - case CANCEL_TASK_METHOD -> { - io.a2a.grpc.Task.Builder builder = io.a2a.grpc.Task.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return new CancelTaskResponse(id, ProtoUtils.FromProto.task(builder)); - } - case LIST_TASK_METHOD -> { - io.a2a.grpc.ListTasksResponse.Builder builder = io.a2a.grpc.ListTasksResponse.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return new ListTasksResponse(id, ProtoUtils.FromProto.listTasksResult(builder)); - } - case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return new CreateTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.taskPushNotificationConfig(builder)); - } - case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return new GetTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.taskPushNotificationConfig(builder)); - } - case SEND_MESSAGE_METHOD -> { - io.a2a.grpc.SendMessageResponse.Builder builder = io.a2a.grpc.SendMessageResponse.newBuilder(); - parseRequestBody(paramsNode, builder, id); - if (builder.hasMessage()) { - return new SendMessageResponse(id, ProtoUtils.FromProto.message(builder.getMessage())); - } - return new SendMessageResponse(id, ProtoUtils.FromProto.task(builder.getTask())); - } - case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return new ListTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.listTaskPushNotificationConfigResult(builder)); - } - case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - return new DeleteTaskPushNotificationConfigResponse(id); - } - case GET_EXTENDED_AGENT_CARD_METHOD -> { - io.a2a.grpc.AgentCard.Builder builder = io.a2a.grpc.AgentCard.newBuilder(); - parseRequestBody(paramsNode, builder, id); - return new GetExtendedAgentCardResponse(id, ProtoUtils.FromProto.agentCard(builder)); - } - default -> - throw new MethodNotFoundJsonMappingException("Unsupported JSON-RPC method: '" + method + "' in response parsing.", getIdIfPossible(jsonRpc)); - } - } - - public static A2AResponse parseError(JsonObject error, Object id, String method) throws JsonMappingException { - A2AError rpcError = processError(error); - switch (method) { - case GET_TASK_METHOD -> { - return new GetTaskResponse(id, rpcError); - } - case CANCEL_TASK_METHOD -> { - return new CancelTaskResponse(id, rpcError); - } - case LIST_TASK_METHOD -> { - return new ListTasksResponse(id, rpcError); - } - case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - return new CreateTaskPushNotificationConfigResponse(id, rpcError); - } - case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - return new GetTaskPushNotificationConfigResponse(id, rpcError); - } - case SEND_MESSAGE_METHOD -> { - return new SendMessageResponse(id, rpcError); - } - case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - return new ListTaskPushNotificationConfigResponse(id, rpcError); - } - case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { - return new DeleteTaskPushNotificationConfigResponse(id, rpcError); - } - default -> - throw new MethodNotFoundJsonMappingException("Unsupported JSON-RPC method: '" + method + "'", id); - } - } - - private static A2AError processError(JsonObject error) { - String message = error.has("message") ? error.get("message").getAsString() : null; - Integer code = error.has("code") ? error.get("code").getAsInt() : null; - String data = error.has("data") ? error.get("data").toString() : null; - if (code != null) { - switch (code) { - case JSON_PARSE_ERROR_CODE: - return new JSONParseError(code, message, data); - case INVALID_REQUEST_ERROR_CODE: - return new InvalidRequestError(code, message, data); - case METHOD_NOT_FOUND_ERROR_CODE: - return new MethodNotFoundError(code, message, data); - case INVALID_PARAMS_ERROR_CODE: - return new InvalidParamsError(code, message, data); - case INTERNAL_ERROR_CODE: - return new io.a2a.spec.InternalError(code, message, data); - case PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE: - return new PushNotificationNotSupportedError(code, message, data); - case UNSUPPORTED_OPERATION_ERROR_CODE: - return new UnsupportedOperationError(code, message, data); - case CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE: - return new ContentTypeNotSupportedError(code, message, data); - case INVALID_AGENT_RESPONSE_ERROR_CODE: - return new InvalidAgentResponseError(code, message, data); - case EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE: - return new ExtendedAgentCardNotConfiguredError(code, message, data); - case EXTENSION_SUPPORT_REQUIRED_ERROR: - return new ExtensionSupportRequiredError(code, message, data); - case VERSION_NOT_SUPPORTED_ERROR_CODE: - return new VersionNotSupportedError(code, message, data); - case TASK_NOT_CANCELABLE_ERROR_CODE: - return new TaskNotCancelableError(code, message, data); - case TASK_NOT_FOUND_ERROR_CODE: - return new TaskNotFoundError(code, message, data); - default: - return new A2AError(code, message == null ? "": message, data); - } - } - return new A2AError(INTERNAL_ERROR_CODE, message == null ? "": message, data); - } - - protected static void parseRequestBody(JsonElement jsonRpc, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException { - parseJsonString(jsonRpc.toString(), builder, id); - } - - public static void parseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException { - try { - JsonFormat.parser().merge(body, builder); - } catch (InvalidProtocolBufferException e) { - log.log(Level.FINE, "Protocol buffer parsing failed for JSON: {0}", body); - log.log(Level.FINE, "Proto parsing error details", e); - throw convertProtoBufExceptionToJsonProcessingException(e, id); - } - } - - /** - * Extracts a user-friendly error message from Protocol Buffer parsing exceptions. - *

    - * This method converts low-level protobuf exceptions into appropriate JsonProcessingException: - *

      - *
    • {@link InvalidParamsJsonMappingException} - When the request ID is known and the error - * is related to invalid parameter structure (wrong type, missing field, invalid value). - * This maps to JSON-RPC error code -32602 (Invalid params).
    • - *
    • {@link JsonProcessingException} - When the request ID is unknown and the error is - * related to malformed JSON structure. This maps to JSON-RPC error code -32700 (Parse error).
    • - *
    • {@link JsonMappingException} - When the error doesn't fit specific patterns and we - * cannot determine the exact error type. This is a generic JSON-RPC error.
    • - *
    - *

    - * ID Handling: When the request ID is null, we use an empty string ("") as a sentinel value - * for InvalidParamsJsonMappingException. This is required because the JSON-RPC spec mandates that - * error responses must include the request ID if it could be determined. An empty string indicates - * "we tried to get the ID but it was invalid/missing", while a null JsonMappingException indicates - * "we couldn't even parse enough to attempt ID extraction". - * - * @param e the InvalidProtocolBufferException from proto parsing - * @param id the request ID if it could be extracted, null otherwise - * @return an appropriate JsonProcessingException subtype based on the error and ID availability - */ - private static JsonProcessingException convertProtoBufExceptionToJsonProcessingException(InvalidProtocolBufferException e, Object id) { - // Log the original exception for debugging purposes - log.log(Level.FINE, "Converting protobuf parsing exception to JSON-RPC error. Request ID: {0}", id); - log.log(Level.FINE, "Original proto exception details", e); - - String message = e.getMessage(); - if (message == null) { - return new JsonProcessingException(ERROR_MESSAGE.formatted("unknown parsing error")); - } - - // Extract field name if present in error message - check common prefixes - String[] prefixes = {"Cannot find field: ", "Invalid value for", "Invalid enum value:", "Failed to parse"}; - for (String prefix : prefixes) { - if (message.contains(prefix)) { - return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(message.substring(message.indexOf(prefix) + prefix.length())), id); - } - } - - // Try to extract specific error details using regex patterns - Matcher matcher = EXTRACT_WRONG_TYPE.matcher(message); - if (matcher.matches() && matcher.group(1) != null) { - // ID is null -> use empty string sentinel value (see javadoc above) - return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(matcher.group(1)), Utils.defaultIfNull(id, "")); - } - matcher = EXTRACT_WRONG_VALUE.matcher(message); - if (matcher.matches() && matcher.group(1) != null) { - // ID is null -> use empty string sentinel value (see javadoc above) - return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(matcher.group(1)), Utils.defaultIfNull(id, "")); - } - - // Generic error - couldn't match specific patterns - return new JsonMappingException(ERROR_MESSAGE.formatted(message)); - } - - protected static String getAndValidateJsonrpc(JsonObject jsonRpc) throws JsonMappingException { - if (!jsonRpc.has("jsonrpc")) { - throw new IdJsonMappingException( - "Missing required 'jsonrpc' field. All requests must include 'jsonrpc': '2.0'", - getIdIfPossible(jsonRpc)); - } - String version = jsonRpc.get("jsonrpc").getAsString(); - if (!A2AMessage.JSONRPC_VERSION.equals(version)) { - throw new IdJsonMappingException( - "Unsupported JSON-RPC version: '" + version + "'. Expected version '2.0'", - getIdIfPossible(jsonRpc)); - } - return version; - } - - /** - * Try to get the request id if possible , returns "UNDETERMINED ID" otherwise. - * This should be only used for errors. - * - * @param jsonRpc the json rpc JSON. - * @return the request id if possible , "UNDETERMINED ID" otherwise. - */ - protected static Object getIdIfPossible(JsonObject jsonRpc) { - try { - return getAndValidateId(jsonRpc); - } catch (JsonMappingException e) { - // id can't be determined - return "UNDETERMINED ID"; - } - } - - protected static Object getAndValidateId(JsonObject jsonRpc) throws JsonMappingException { - Object id = null; - if (jsonRpc.has("id")) { - if (jsonRpc.get("id").isJsonPrimitive()) { - try { - id = jsonRpc.get("id").getAsInt(); - } catch (UnsupportedOperationException | NumberFormatException | IllegalStateException e) { - id = jsonRpc.get("id").getAsString(); - } - } else { - throw new JsonMappingException(null, "Invalid 'id' type: " + jsonRpc.get("id").getClass().getSimpleName() - + ". ID must be a JSON string or number, not an object or array."); - } - } - if (id == null) { - throw new JsonMappingException(null, "Request 'id' cannot be null. Use a string or number identifier."); - } - return id; - } - - public static String toJsonRPCRequest(@Nullable String requestId, String method, com.google.protobuf.@Nullable MessageOrBuilder payload) { - try (StringWriter result = new StringWriter(); JsonWriter output = GSON.newJsonWriter(result)) { - output.beginObject(); - output.name("jsonrpc").value("2.0"); - String id = requestId; - if (requestId == null) { - id = UUID.randomUUID().toString(); - } - output.name("id").value(id); - if (method != null) { - output.name("method").value(method); - } - if (payload != null) { - String resultValue = JsonFormat.printer().includingDefaultValueFields().omittingInsignificantWhitespace().print(payload); - output.name("params").jsonValue(resultValue); - } - output.endObject(); - return result.toString(); - } catch (IOException ex) { - throw new RuntimeException( - "Failed to serialize JSON-RPC request for method '" + method + "'. " - + "This indicates an internal error in JSON generation. Request ID: " + requestId, ex); - } - } - - public static String toJsonRPCResultResponse(Object requestId, com.google.protobuf.MessageOrBuilder builder) { - try (StringWriter result = new StringWriter(); JsonWriter output = GSON.newJsonWriter(result)) { - output.beginObject(); - output.name("jsonrpc").value("2.0"); - if (requestId != null) { - if (requestId instanceof String string) { - output.name("id").value(string); - } else if (requestId instanceof Number number) { - output.name("id").value(number.longValue()); - } - } - String resultValue = JsonFormat.printer().includingDefaultValueFields().omittingInsignificantWhitespace().print(builder); - output.name("result").jsonValue(resultValue); - output.endObject(); - return result.toString(); - } catch (IOException ex) { - throw new RuntimeException( - "Failed to serialize JSON-RPC success response. " - + "Proto type: " + builder.getClass().getSimpleName() + ", Request ID: " + requestId, ex); - } - } - - public static String toJsonRPCErrorResponse(Object requestId, A2AError error) { - try (StringWriter result = new StringWriter(); JsonWriter output = GSON.newJsonWriter(result)) { - output.beginObject(); - output.name("jsonrpc").value("2.0"); - if (requestId != null) { - if (requestId instanceof String string) { - output.name("id").value(string); - } else if (requestId instanceof Number number) { - output.name("id").value(number.longValue()); - } - } - output.name("error"); - output.beginObject(); - output.name("code").value(error.getCode()); - output.name("message").value(error.getMessage()); - if (error.getData() != null) { - output.name("data").value(error.getData().toString()); - } - output.endObject(); - output.endObject(); - return result.toString(); - } catch (IOException ex) { - throw new RuntimeException( - "Failed to serialize JSON-RPC error response. " - + "Error code: " + error.getCode() + ", Request ID: " + requestId, ex); - } - } -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java b/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java deleted file mode 100644 index d4b1ca55f..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java +++ /dev/null @@ -1,335 +0,0 @@ -package io.a2a.grpc.utils; - -import java.util.ArrayList; -import java.util.List; - -import io.a2a.grpc.GetExtendedAgentCardRequest; -import io.a2a.grpc.StreamResponse; -import io.a2a.grpc.mapper.AgentCardMapper; -import io.a2a.grpc.mapper.DeleteTaskPushNotificationConfigParamsMapper; -import io.a2a.grpc.mapper.GetTaskPushNotificationConfigParamsMapper; -import io.a2a.grpc.mapper.ListTaskPushNotificationConfigParamsMapper; -import io.a2a.grpc.mapper.ListTasksParamsMapper; -import io.a2a.grpc.mapper.ListTasksResultMapper; -import io.a2a.grpc.mapper.MessageMapper; -import io.a2a.grpc.mapper.MessageSendConfigurationMapper; -import io.a2a.grpc.mapper.MessageSendParamsMapper; -import io.a2a.grpc.mapper.CreateTaskPushNotificationConfigMapper; -import io.a2a.grpc.mapper.StreamResponseMapper; -import io.a2a.grpc.mapper.TaskArtifactUpdateEventMapper; -import io.a2a.grpc.mapper.TaskIdParamsMapper; -import io.a2a.grpc.mapper.TaskMapper; -import io.a2a.grpc.mapper.TaskPushNotificationConfigMapper; -import io.a2a.grpc.mapper.TaskQueryParamsMapper; -import io.a2a.grpc.mapper.TaskStateMapper; -import io.a2a.grpc.mapper.TaskStatusUpdateEventMapper; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.spec.AgentCard; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; - -/** - * Utility class to convert between GRPC and Spec objects. - */ -public class ProtoUtils { - - public static class ToProto { - - public static io.a2a.grpc.AgentCard agentCard(AgentCard agentCard) { - return AgentCardMapper.INSTANCE.toProto(agentCard); - } - - public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard() { - return GetExtendedAgentCardRequest.newBuilder().build(); - } - - public static io.a2a.grpc.GetTaskRequest getTaskRequest(TaskQueryParams params) { - return TaskQueryParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.CancelTaskRequest cancelTaskRequest(TaskIdParams params) { - return TaskIdParamsMapper.INSTANCE.toProtoCancelTaskRequest(params); - } - - public static io.a2a.grpc.SubscribeToTaskRequest subscribeToTaskRequest(TaskIdParams params) { - return TaskIdParamsMapper.INSTANCE.toProtoSubscribeToTaskRequest(params); - } - - public static io.a2a.grpc.CreateTaskPushNotificationConfigRequest createTaskPushNotificationConfigRequest(TaskPushNotificationConfig config) { - return CreateTaskPushNotificationConfigMapper.INSTANCE.toProto(config); - } - - public static io.a2a.grpc.GetTaskPushNotificationConfigRequest getTaskPushNotificationConfigRequest(GetTaskPushNotificationConfigParams params) { - return GetTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.DeleteTaskPushNotificationConfigRequest deleteTaskPushNotificationConfigRequest(DeleteTaskPushNotificationConfigParams params) { - return DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigRequest listTaskPushNotificationConfigRequest(ListTaskPushNotificationConfigParams params) { - return ListTaskPushNotificationConfigParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.Task task(Task task) { - return TaskMapper.INSTANCE.toProto(task); - } - - public static io.a2a.grpc.ListTasksResponse listTasksResult(ListTasksResult result) { - return ListTasksResultMapper.INSTANCE.toProto(result); - } - - public static io.a2a.grpc.ListTasksRequest listTasksParams(ListTasksParams params) { - return ListTasksParamsMapper.INSTANCE.toProto(params); - } - - public static io.a2a.grpc.Message message(Message message) { - return MessageMapper.INSTANCE.toProto(message); - } - - public static io.a2a.grpc.TaskPushNotificationConfig taskPushNotificationConfig(TaskPushNotificationConfig config) { - return TaskPushNotificationConfigMapper.INSTANCE.toProto(config); - } - - public static io.a2a.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent(TaskArtifactUpdateEvent event) { - return TaskArtifactUpdateEventMapper.INSTANCE.toProto(event); - } - - public static io.a2a.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent(TaskStatusUpdateEvent event) { - return TaskStatusUpdateEventMapper.INSTANCE.toProto(event); - } - - public static io.a2a.grpc.TaskState taskState(TaskState taskState) { - return TaskStateMapper.INSTANCE.toProto(taskState); - } - - public static io.a2a.grpc.SendMessageConfiguration messageSendConfiguration(MessageSendConfiguration messageSendConfiguration) { - return MessageSendConfigurationMapper.INSTANCE.toProto(messageSendConfiguration); - } - - public static io.a2a.grpc.SendMessageRequest sendMessageRequest(MessageSendParams request) { - return MessageSendParamsMapper.INSTANCE.toProto(request); - } - - public static io.a2a.grpc.ListTaskPushNotificationConfigResponse listTaskPushNotificationConfigResponse(ListTaskPushNotificationConfigResult result) { - List confs = new ArrayList<>(result.configs().size()); - for (TaskPushNotificationConfig config : result.configs()) { - confs.add(taskPushNotificationConfig(config)); - } - io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder().addAllConfigs(confs); - if (result.nextPageToken() != null) { - builder.setNextPageToken(result.nextPageToken()); - } - return builder.build(); - } - - public static StreamResponse streamResponse(StreamingEventKind streamingEventKind) { - return StreamResponseMapper.INSTANCE.toProto(streamingEventKind); - } - - public static io.a2a.grpc.SendMessageResponse taskOrMessage(EventKind eventKind) { - return switch (eventKind.kind()) { - case Task.STREAMING_EVENT_ID -> io.a2a.grpc.SendMessageResponse.newBuilder() - .setTask(task((Task) eventKind)) - .build(); - case Message.STREAMING_EVENT_ID -> io.a2a.grpc.SendMessageResponse.newBuilder() - .setMessage(message((Message) eventKind)) - .build(); - default -> throw new IllegalArgumentException("Unsupported event type: " + eventKind); - }; - } - - public static io.a2a.grpc.StreamResponse taskOrMessageStream(StreamingEventKind eventKind) { - return switch (eventKind.kind()) { - case Task.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setTask(task((Task) eventKind)) - .build(); - case Message.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setMessage(message((Message) eventKind)) - .build(); - case TaskStatusUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setStatusUpdate(taskStatusUpdateEvent((TaskStatusUpdateEvent) eventKind)) - .build(); - case TaskArtifactUpdateEvent.STREAMING_EVENT_ID -> io.a2a.grpc.StreamResponse.newBuilder() - .setArtifactUpdate(taskArtifactUpdateEvent((TaskArtifactUpdateEvent) eventKind)) - .build(); - default -> throw new IllegalArgumentException("Unsupported event type: " + eventKind); - }; - } - - public static io.a2a.grpc.TaskPushNotificationConfig createTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { - return taskPushNotificationConfig(config); - } - - public static io.a2a.grpc.TaskPushNotificationConfig getTaskPushNotificationConfigResponse(TaskPushNotificationConfig config) { - return taskPushNotificationConfig(config); - } - - public static io.a2a.grpc.AgentCard getExtendedCardResponse(AgentCard card) { - return agentCard(card); - } - } - - public static class FromProto { - - private static T convert(java.util.function.Supplier s) { - try { - return s.get(); - } catch (IllegalArgumentException ex) { - throw new InvalidParamsError(ex.getMessage()); - } - } - - public static AgentCard agentCard(io.a2a.grpc.AgentCardOrBuilder agentCard) { - io.a2a.grpc.AgentCard agentCardProto = agentCard instanceof io.a2a.grpc.AgentCard - ? (io.a2a.grpc.AgentCard) agentCard - : ((io.a2a.grpc.AgentCard.Builder) agentCard).build(); - return convert(() -> AgentCardMapper.INSTANCE.fromProto(agentCardProto)); - } - - public static TaskQueryParams taskQueryParams(io.a2a.grpc.GetTaskRequestOrBuilder request) { - io.a2a.grpc.GetTaskRequest reqProto = request instanceof io.a2a.grpc.GetTaskRequest - ? (io.a2a.grpc.GetTaskRequest) request - : ((io.a2a.grpc.GetTaskRequest.Builder) request).build(); - return convert(() -> TaskQueryParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static ListTasksParams listTasksParams(io.a2a.grpc.ListTasksRequestOrBuilder request) { - io.a2a.grpc.ListTasksRequest reqProto = request instanceof io.a2a.grpc.ListTasksRequest - ? (io.a2a.grpc.ListTasksRequest) request - : ((io.a2a.grpc.ListTasksRequest.Builder) request).build(); - return convert(() -> ListTasksParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static TaskIdParams taskIdParams(io.a2a.grpc.CancelTaskRequestOrBuilder request) { - io.a2a.grpc.CancelTaskRequest reqProto = request instanceof io.a2a.grpc.CancelTaskRequest - ? (io.a2a.grpc.CancelTaskRequest) request - : ((io.a2a.grpc.CancelTaskRequest.Builder) request).build(); - return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoCancelTaskRequest(reqProto)); - } - - public static MessageSendParams messageSendParams(io.a2a.grpc.SendMessageRequestOrBuilder request) { - io.a2a.grpc.SendMessageRequest requestProto = request instanceof io.a2a.grpc.SendMessageRequest - ? (io.a2a.grpc.SendMessageRequest) request - : ((io.a2a.grpc.SendMessageRequest.Builder) request).build(); - return convert(() -> MessageSendParamsMapper.INSTANCE.fromProto(requestProto)); - } - - public static TaskPushNotificationConfig CreateTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequestOrBuilder config) { - io.a2a.grpc.CreateTaskPushNotificationConfigRequest reqProto = config instanceof io.a2a.grpc.CreateTaskPushNotificationConfigRequest - ? (io.a2a.grpc.CreateTaskPushNotificationConfigRequest) config - : ((io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder) config).build(); - return convert(() -> CreateTaskPushNotificationConfigMapper.INSTANCE.fromProto(reqProto)); - } - - public static TaskPushNotificationConfig taskPushNotificationConfig(io.a2a.grpc.TaskPushNotificationConfigOrBuilder config) { - io.a2a.grpc.TaskPushNotificationConfig proto = config instanceof io.a2a.grpc.TaskPushNotificationConfig - ? (io.a2a.grpc.TaskPushNotificationConfig) config - : ((io.a2a.grpc.TaskPushNotificationConfig.Builder) config).build(); - return convert(() -> TaskPushNotificationConfigMapper.INSTANCE.fromProto(proto)); - } - - public static GetTaskPushNotificationConfigParams getTaskPushNotificationConfigParams(io.a2a.grpc.GetTaskPushNotificationConfigRequestOrBuilder request) { - io.a2a.grpc.GetTaskPushNotificationConfigRequest reqProto = request instanceof io.a2a.grpc.GetTaskPushNotificationConfigRequest - ? (io.a2a.grpc.GetTaskPushNotificationConfigRequest) request - : ((io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder) request).build(); - return convert(() -> GetTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static TaskIdParams taskIdParams(io.a2a.grpc.SubscribeToTaskRequestOrBuilder request) { - io.a2a.grpc.SubscribeToTaskRequest reqProto = request instanceof io.a2a.grpc.SubscribeToTaskRequest - ? (io.a2a.grpc.SubscribeToTaskRequest) request - : ((io.a2a.grpc.SubscribeToTaskRequest.Builder) request).build(); - return convert(() -> TaskIdParamsMapper.INSTANCE.fromProtoSubscribeToTaskRequest(reqProto)); - } - - public static ListTaskPushNotificationConfigResult listTaskPushNotificationConfigResult(io.a2a.grpc.ListTaskPushNotificationConfigResponseOrBuilder response) { - List configs = response.getConfigsList(); - List result = new ArrayList<>(configs.size()); - for (io.a2a.grpc.TaskPushNotificationConfig config : configs) { - result.add(taskPushNotificationConfig(config)); - } - String nextPageToken = response.getNextPageToken(); - if (nextPageToken != null && nextPageToken.isEmpty()) { - nextPageToken = null; - } - return new ListTaskPushNotificationConfigResult(result, nextPageToken); - } - - public static ListTaskPushNotificationConfigParams listTaskPushNotificationConfigParams(io.a2a.grpc.ListTaskPushNotificationConfigRequestOrBuilder request) { - io.a2a.grpc.ListTaskPushNotificationConfigRequest reqProto = request instanceof io.a2a.grpc.ListTaskPushNotificationConfigRequest - ? (io.a2a.grpc.ListTaskPushNotificationConfigRequest) request - : ((io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder) request).build(); - return convert(() -> ListTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static DeleteTaskPushNotificationConfigParams deleteTaskPushNotificationConfigParams(io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder request) { - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest reqProto = request instanceof io.a2a.grpc.DeleteTaskPushNotificationConfigRequest - ? (io.a2a.grpc.DeleteTaskPushNotificationConfigRequest) request - : ((io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder) request).build(); - return convert(() -> DeleteTaskPushNotificationConfigParamsMapper.INSTANCE.fromProto(reqProto)); - } - - public static Task task(io.a2a.grpc.TaskOrBuilder task) { - io.a2a.grpc.Task taskProto = task instanceof io.a2a.grpc.Task - ? (io.a2a.grpc.Task) task - : ((io.a2a.grpc.Task.Builder) task).build(); - return convert(() -> TaskMapper.INSTANCE.fromProto(taskProto)); - } - - public static Message message(io.a2a.grpc.MessageOrBuilder message) { - if (message.getMessageId().isEmpty()) { - throw new InvalidParamsError(); - } - io.a2a.grpc.Message messageProto = message instanceof io.a2a.grpc.Message - ? (io.a2a.grpc.Message) message - : ((io.a2a.grpc.Message.Builder) message).build(); - return convert(() -> MessageMapper.INSTANCE.fromProto(messageProto)); - } - - public static TaskStatusUpdateEvent taskStatusUpdateEvent(io.a2a.grpc.TaskStatusUpdateEventOrBuilder taskStatusUpdateEvent) { - io.a2a.grpc.TaskStatusUpdateEvent eventProto = taskStatusUpdateEvent instanceof io.a2a.grpc.TaskStatusUpdateEvent - ? (io.a2a.grpc.TaskStatusUpdateEvent) taskStatusUpdateEvent - : ((io.a2a.grpc.TaskStatusUpdateEvent.Builder) taskStatusUpdateEvent).build(); - return convert(() -> TaskStatusUpdateEventMapper.INSTANCE.fromProto(eventProto)); - } - - public static TaskArtifactUpdateEvent taskArtifactUpdateEvent(io.a2a.grpc.TaskArtifactUpdateEventOrBuilder taskArtifactUpdateEvent) { - io.a2a.grpc.TaskArtifactUpdateEvent eventProto = taskArtifactUpdateEvent instanceof io.a2a.grpc.TaskArtifactUpdateEvent - ? (io.a2a.grpc.TaskArtifactUpdateEvent) taskArtifactUpdateEvent - : ((io.a2a.grpc.TaskArtifactUpdateEvent.Builder) taskArtifactUpdateEvent).build(); - return convert(() -> TaskArtifactUpdateEventMapper.INSTANCE.fromProto(eventProto)); - } - - public static ListTasksResult listTasksResult(io.a2a.grpc.ListTasksResponseOrBuilder listTasksResponse) { - io.a2a.grpc.ListTasksResponse eventProto = listTasksResponse instanceof io.a2a.grpc.ListTasksResponse - ? (io.a2a.grpc.ListTasksResponse) listTasksResponse - : ((io.a2a.grpc.ListTasksResponse.Builder) listTasksResponse).build(); - return convert(() -> ListTasksResultMapper.INSTANCE.fromProto(eventProto)); - } - - public static StreamingEventKind streamingEventKind(io.a2a.grpc.StreamResponseOrBuilder streamResponse) { - io.a2a.grpc.StreamResponse streamResponseProto = streamResponse instanceof io.a2a.grpc.StreamResponse - ? (io.a2a.grpc.StreamResponse) streamResponse - : ((io.a2a.grpc.StreamResponse.Builder) streamResponse).build(); - return convert(() -> StreamResponseMapper.INSTANCE.fromProto(streamResponseProto)); - } - } - -} diff --git a/spec-grpc/src/main/java/io/a2a/grpc/utils/package-info.java b/spec-grpc/src/main/java/io/a2a/grpc/utils/package-info.java deleted file mode 100644 index 526496e36..000000000 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.grpc.utils; - -import org.jspecify.annotations.NullMarked; - diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto deleted file mode 100644 index 97157cce8..000000000 --- a/spec-grpc/src/main/proto/a2a.proto +++ /dev/null @@ -1,897 +0,0 @@ -// Older protoc compilers don't understand edition yet. -syntax = "proto3"; -package a2a.v1; - -import "google/api/annotations.proto"; -import "google/api/client.proto"; -import "google/api/field_behavior.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/struct.proto"; -import "google/protobuf/timestamp.proto"; - -//From commit b86d8bb2edd20a972951666823cf6c9f51317550 - -option csharp_namespace = "A2a.V1"; -option go_package = "google.golang.org/a2a/v1"; -option java_multiple_files = true; -option java_outer_classname = "A2A"; -option java_package = "io.a2a.grpc"; - -// A2AService defines the operations of the A2A protocol. -service A2AService { - // Send a message to the agent. - rpc SendMessage(SendMessageRequest) returns (SendMessageResponse) { - option (google.api.http) = { - post: "/message:send" - body: "*" - additional_bindings: { - post: "/{tenant}/message:send" - body: "*" - } - }; - } - // SendStreamingMessage is a streaming version of SendMessage. - rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse) { - option (google.api.http) = { - post: "/message:stream" - body: "*" - additional_bindings: { - post: "/{tenant}/message:stream" - body: "*" - } - }; - } - - // Get the current state of a task from the agent. - rpc GetTask(GetTaskRequest) returns (Task) { - option (google.api.http) = { - get: "/tasks/{id=*}" - additional_bindings: { - get: "/{tenant}/tasks/{id=*}" - } - }; - option (google.api.method_signature) = "id"; - } - // List tasks with optional filtering and pagination. - rpc ListTasks(ListTasksRequest) returns (ListTasksResponse) { - option (google.api.http) = { - get: "/tasks" - additional_bindings: { - get: "/{tenant}/tasks" - } - }; - } - // Cancel a task. - rpc CancelTask(CancelTaskRequest) returns (Task) { - option (google.api.http) = { - post: "/tasks/{id=*}:cancel" - body: "*" - additional_bindings: { - post: "/{tenant}/tasks/{id=*}:cancel" - body: "*" - } - }; - } - // SubscribeToTask allows subscribing to task updates for tasks not in terminal state. - // Returns UnsupportedOperationError if task is in terminal state (completed, failed, canceled, rejected). - rpc SubscribeToTask(SubscribeToTaskRequest) returns (stream StreamResponse) { - option (google.api.http) = { - get: "/tasks/{id=*}:subscribe" - additional_bindings: { - get: "/{tenant}/tasks/{id=*}:subscribe" - } - }; - } - - // Create a push notification config for a task. - rpc CreateTaskPushNotificationConfig(CreateTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { - option (google.api.http) = { - post: "/tasks/{task_id=*}/pushNotificationConfigs" - body: "config" - additional_bindings: { - post: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs" - body: "config" - } - }; - option (google.api.method_signature) = "task_id,config"; - } - // Get a push notification config for a task. - rpc GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { - option (google.api.http) = { - get: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" - additional_bindings: { - get: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" - } - }; - option (google.api.method_signature) = "task_id,id"; - } - // Get a list of push notifications configured for a task. - rpc ListTaskPushNotificationConfig(ListTaskPushNotificationConfigRequest) returns (ListTaskPushNotificationConfigResponse) { - option (google.api.http) = { - get: "/tasks/{task_id=*}/pushNotificationConfigs" - additional_bindings: { - get: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs" - } - }; - option (google.api.method_signature) = "task_id"; - } - // GetExtendedAgentCard returns the extended agent card for authenticated agents. - rpc GetExtendedAgentCard(GetExtendedAgentCardRequest) returns (AgentCard) { - option (google.api.http) = { - get: "/extendedAgentCard" - additional_bindings: { - get: "/{tenant}/extendedAgentCard" - } - }; - } - // Delete a push notification config for a task. - rpc DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest) returns (google.protobuf.Empty) { - option (google.api.http) = { - delete: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" - additional_bindings: { - delete: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" - } - }; - option (google.api.method_signature) = "task_id,id"; - } -} - -///////// Data Model //////////// - -// --8<-- [start:SendMessageConfiguration] -// Configuration of a send message request. -message SendMessageConfiguration { - // A list of media types the client is prepared to accept for response parts. Agents SHOULD use this to tailor their output. - repeated string accepted_output_modes = 1; - // Configuration for the agent to send push notifications for task updates. - PushNotificationConfig push_notification_config = 2; - // The maximum number of most recent messages from the task's history to retrieve in - // the response. An unset value means the client does not impose any limit. A - // value of zero is a request to not include any messages. The server MUST NOT - // return more messages than the provided value, but MAY apply a lower limit. - optional int32 history_length = 3; - // If true, the operation waits until the task reaches a terminal or interrupted state before returning. Default is false. - bool blocking = 4; -} -// --8<-- [end:SendMessageConfiguration] - -// --8<-- [start:Task] -// Task is the core unit of action for A2A. It has a current status -// and when results are created for the task they are stored in the -// artifact. If there are multiple turns for a task, these are stored in -// history. -message Task { - // Unique identifier (e.g. UUID) for the task, generated by the server for a - // new task. - string id = 1 [(google.api.field_behavior) = REQUIRED]; - // Unique identifier (e.g. UUID) for the contextual collection of interactions - // (tasks and messages). Created by the A2A server. - string context_id = 2 [(google.api.field_behavior) = REQUIRED]; - // The current status of a Task, including state and a message. - TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; - // A set of output artifacts for a Task. - repeated Artifact artifacts = 4; - // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED - // The history of interactions from a task. - repeated Message history = 5; - // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED - // A key/value object to store custom metadata about a task. - google.protobuf.Struct metadata = 6; -} -// --8<-- [end:Task] - -// --8<-- [start:TaskState] -// Defines the possible lifecycle states of a Task. -enum TaskState { - // The task is in an unknown or indeterminate state. - TASK_STATE_UNSPECIFIED = 0; - // Represents the status that acknowledges a task is created. - TASK_STATE_SUBMITTED = 1; - // Represents the status that a task is actively being processed. - TASK_STATE_WORKING = 2; - // Represents the status a task is finished. This is a terminal state. - TASK_STATE_COMPLETED = 3; - // Represents the status a task is done but failed. This is a terminal state. - TASK_STATE_FAILED = 4; - // Represents the status a task was canceled before it finished. - // This is a terminal state. - TASK_STATE_CANCELED = 5; - // Represents the status that the task requires information to complete. - // This is an interrupted state. - TASK_STATE_INPUT_REQUIRED = 6; - // Represents the status that the agent has decided to not perform the task. - // This may be done during initial task creation or later once an agent - // has determined it can't or won't proceed. This is a terminal state. - TASK_STATE_REJECTED = 7; - // Represents the state that some authentication is needed from the upstream - // client. This is an interrupted state. Authentication is expected to come out-of-band. - TASK_STATE_AUTH_REQUIRED = 8; -} -// --8<-- [end:TaskState] - -// --8<-- [start:TaskStatus] -// A container for the status of a task -message TaskStatus { - // The current state of this task. - TaskState state = 1 [(google.api.field_behavior) = REQUIRED]; - // A message associated with the status. - Message message = 2; - // ISO 8601 Timestamp when the status was recorded. - // Example: "2023-10-27T10:00:00Z" - google.protobuf.Timestamp timestamp = 3; -} -// --8<-- [end:TaskStatus] - -// --8<-- [start:Part] -// Part represents a container for a section of communication content. -// Parts can be purely textual, some sort of file (image, video, etc) or -// a structured data blob (i.e. JSON). -message Part { - oneof content { - // The string content of the text part. - string text = 1; - // The raw byte content of a file. In JSON serialization, this is encoded as a base64 string. - bytes raw = 2; - // A URL pointing to the file's content. - string url = 3; - // Arbitrary structured data as a JSON value (object, array, string, number, boolean, or null). - google.protobuf.Value data = 4; - } - // Optional metadata associated with this part. - google.protobuf.Struct metadata = 5; - // An optional name for the file (e.g., "document.pdf"). - string filename = 6; - // The media type (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png"). - // This field is available for all part types. - string media_type = 7; -} -// --8<-- [end:Part] - -// --8<-- [start:Role] -// Defines the sender of a message in A2A protocol communication. -enum Role { - ROLE_UNSPECIFIED = 0; - // USER role refers to communication from the client to the server. - ROLE_USER = 1; - // AGENT role refers to communication from the server to the client. - ROLE_AGENT = 2; -} -// --8<-- [end:Role] - -// --8<-- [start:Message] -// Message is one unit of communication between client and server. It can be -// associated with a context and/or a task. For server messages, context_id must -// be provided, and task_id only if a task was created. For client messages, both -// fields are optional, with the caveat that if both are provided, they have to -// match (the context_id has to be the one that is set on the task). If only -// task_id is provided, the server will infer context_id from it. -message Message { - // The unique identifier (e.g. UUID) of the message. This is required and - // created by the message creator. - string message_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The context id of the message. This is optional and if set, the message - // will be associated with the given context. - string context_id = 2; - // The task id of the message. This is optional and if set, the message - // will be associated with the given task. - string task_id = 3; - // Identifies the sender of the message. - Role role = 4 [(google.api.field_behavior) = REQUIRED]; - // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED - // Parts is the container of the message content. - repeated Part parts = 5 [(google.api.field_behavior) = REQUIRED]; - // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED - // Any optional metadata to provide along with the message. - google.protobuf.Struct metadata = 6; - // The URIs of extensions that are present or contributed to this Message. - repeated string extensions = 7; - // A list of task IDs that this message references for additional context. - repeated string reference_task_ids = 8; -} -// --8<-- [end:Message] - -// --8<-- [start:Artifact] -// Artifacts represent task outputs. -message Artifact { - // Unique identifier (e.g. UUID) for the artifact. It must be at least unique - // within a task. - string artifact_id = 1 [(google.api.field_behavior) = REQUIRED]; - // A human readable name for the artifact. - string name = 3; - // A human readable description of the artifact, optional. - string description = 4; - // The content of the artifact. Must contain at least one part. - repeated Part parts = 5 [(google.api.field_behavior) = REQUIRED]; - // Optional metadata included with the artifact. - google.protobuf.Struct metadata = 6; - // The URIs of extensions that are present or contributed to this Artifact. - repeated string extensions = 7; -} -// --8<-- [end:Artifact] - -// --8<-- [start:TaskStatusUpdateEvent] -// An event sent by the agent to notify the client of a change in a task's -// status. -message TaskStatusUpdateEvent { - // The id of the task that is changed - string task_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The id of the context that the task belongs to - string context_id = 2 [(google.api.field_behavior) = REQUIRED]; - // The new status of the task. - TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; - reserved 4; - // Optional metadata to associate with the task update. - google.protobuf.Struct metadata = 5; -} -// --8<-- [end:TaskStatusUpdateEvent] - -// --8<-- [start:TaskArtifactUpdateEvent] -// TaskArtifactUpdateEvent represents a task delta where an artifact has -// been generated. -message TaskArtifactUpdateEvent { - // The id of the task for this artifact. - string task_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The id of the context that this task belongs to. - string context_id = 2 [(google.api.field_behavior) = REQUIRED]; - // The artifact that was generated or updated. - Artifact artifact = 3 [(google.api.field_behavior) = REQUIRED]; - // If true, the content of this artifact should be appended to a previously - // sent artifact with the same ID. - bool append = 4; - // If true, this is the final chunk of the artifact. - bool last_chunk = 5; - // Optional metadata associated with the artifact update. - google.protobuf.Struct metadata = 6; -} -// --8<-- [end:TaskArtifactUpdateEvent] - -// --8<-- [start:PushNotificationConfig] -// Configuration for setting up push notifications for task updates. -message PushNotificationConfig { - // A unique identifier (e.g. UUID) for this push notification. - string id = 1; - // Url to send the notification too - string url = 2 [(google.api.field_behavior) = REQUIRED]; - // Token unique for this task/session - string token = 3; - // Authentication information required to send the notification - AuthenticationInfo authentication = 4; -} -// --8<-- [end:PushNotificationConfig] - -// --8<-- [start:PushNotificationAuthenticationInfo] -// Defines authentication details, used for push notifications. -message AuthenticationInfo { - // HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/). - // Common values: `Bearer`, `Basic`, `Digest`. Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1). - string scheme = 1 [(google.api.field_behavior) = REQUIRED]; - // Push Notification credentials. Format depends on the scheme (e.g., token for Bearer). - string credentials = 2; -} -// --8<-- [end:PushNotificationAuthenticationInfo] - -// --8<-- [start:AgentInterface] -// Declares a combination of a target URL, transport and protocol version for interacting with the agent. -// This allows agents to expose the same functionality over multiple protocol binding mechanisms. -message AgentInterface { - // The URL where this interface is available. Must be a valid absolute HTTPS URL in production. - // Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a" - string url = 1 [(google.api.field_behavior) = REQUIRED]; - // The protocol binding supported at this URL. This is an open form string, to be - // easily extended for other protocol bindings. The core ones officially - // supported are `JSONRPC`, `GRPC` and `HTTP+JSON`. - string protocol_binding = 2 [(google.api.field_behavior) = REQUIRED]; - // Tenant to be set in the request when calling the agent. - string tenant = 3; - // The version of the A2A protocol this interface exposes. - // Use the latest supported minor version per major version. - // Examples: "0.3", "1.0" - string protocol_version = 4 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:AgentInterface] - -// --8<-- [start:AgentCard] -// AgentCard is a self-describing manifest for an agent. It provides essential -// metadata including the agent's identity, capabilities, skills, supported -// communication methods, and security requirements. -// Next ID: 20 -message AgentCard { - // Reserve these field numbers as they were previously used by removed - // fields. - reserved 3, 9, 14, 15, 16; - // A human readable name for the agent. - // Example: "Recipe Agent" - string name = 1 [(google.api.field_behavior) = REQUIRED]; - // A human-readable description of the agent, assisting users and other agents - // in understanding its purpose. - // Example: "Agent that helps users with recipes and cooking." - string description = 2 [(google.api.field_behavior) = REQUIRED]; - // Ordered list of supported interfaces. First entry is preferred. - repeated AgentInterface supported_interfaces = 19 [(google.api.field_behavior) = REQUIRED]; - // The service provider of the agent. - AgentProvider provider = 4; - // The version of the agent. - // Example: "1.0.0" - string version = 5 [(google.api.field_behavior) = REQUIRED]; - // A url to provide additional documentation about the agent. - optional string documentation_url = 6; - // A2A Capability set supported by the agent. - AgentCapabilities capabilities = 7 [(google.api.field_behavior) = REQUIRED]; - // The security scheme details used for authenticating with this agent. - map security_schemes = 8; - // Security requirements for contacting the agent. - repeated SecurityRequirement security_requirements = 13; - // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED - // The set of interaction modes that the agent supports across all skills. - // This can be overridden per skill. Defined as media types. - repeated string default_input_modes = 10 [(google.api.field_behavior) = REQUIRED]; - // The media types supported as outputs from this agent. - repeated string default_output_modes = 11 [(google.api.field_behavior) = REQUIRED]; - // Skills represent an ability of an agent. It is largely - // a descriptive concept but represents a more focused set of behaviors that the - // agent is likely to succeed at. - repeated AgentSkill skills = 12 [(google.api.field_behavior) = REQUIRED]; - // JSON Web Signatures computed for this AgentCard. - repeated AgentCardSignature signatures = 17; - // An optional URL to an icon for the agent. - optional string icon_url = 18; -} -// --8<-- [end:AgentCard] - -// --8<-- [start:AgentProvider] -// Represents the service provider of an agent. -message AgentProvider { - // A URL for the agent provider's website or relevant documentation. - // Example: "https://ai.google.dev" - string url = 1 [(google.api.field_behavior) = REQUIRED]; - // The name of the agent provider's organization. - // Example: "Google" - string organization = 2 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:AgentProvider] - -// --8<-- [start:AgentCapabilities] -// Defines optional capabilities supported by an agent. -message AgentCapabilities { - // Indicates if the agent supports streaming responses. - optional bool streaming = 1; - // Indicates if the agent supports sending push notifications for asynchronous task updates. - optional bool push_notifications = 2; - // A list of protocol extensions supported by the agent. - repeated AgentExtension extensions = 3; - // Field 4 was previously used by state_transition_history capability. - reserved 4; - // Indicates if the agent supports providing an extended agent card when authenticated. - optional bool extended_agent_card = 5; -} -// --8<-- [end:AgentCapabilities] - -// --8<-- [start:AgentExtension] -// A declaration of a protocol extension supported by an Agent. -message AgentExtension { - // The unique URI identifying the extension. - string uri = 1; - // A human-readable description of how this agent uses the extension. - string description = 2; - // If true, the client must understand and comply with the extension's requirements. - bool required = 3; - // Optional, extension-specific configuration parameters. - google.protobuf.Struct params = 4; -} -// --8<-- [end:AgentExtension] - -// --8<-- [start:AgentSkill] -// Represents a distinct capability or function that an agent can perform. -message AgentSkill { - // A unique identifier for the agent's skill. - string id = 1 [(google.api.field_behavior) = REQUIRED]; - // A human-readable name for the skill. - string name = 2 [(google.api.field_behavior) = REQUIRED]; - // A detailed description of the skill. - string description = 3 [(google.api.field_behavior) = REQUIRED]; - // A set of keywords describing the skill's capabilities. - repeated string tags = 4 [(google.api.field_behavior) = REQUIRED]; - // Example prompts or scenarios that this skill can handle. - repeated string examples = 5; - // The set of supported input media types for this skill, overriding the agent's defaults. - repeated string input_modes = 6; - // The set of supported output media types for this skill, overriding the agent's defaults. - repeated string output_modes = 7; - // Security schemes necessary for this skill. - repeated SecurityRequirement security_requirements = 8; -} -// --8<-- [end:AgentSkill] - -// --8<-- [start:AgentCardSignature] -// AgentCardSignature represents a JWS signature of an AgentCard. -// This follows the JSON format of an RFC 7515 JSON Web Signature (JWS). -message AgentCardSignature { - // The protected JWS header for the signature. This is always a - // base64url-encoded JSON object. Required. - string protected = 1 [(google.api.field_behavior) = REQUIRED]; - // The computed signature, base64url-encoded. Required. - string signature = 2 [(google.api.field_behavior) = REQUIRED]; - // The unprotected JWS header values. - google.protobuf.Struct header = 3; -} -// --8<-- [end:AgentCardSignature] - -// --8<-- [start:TaskPushNotificationConfig] -// A container associating a push notification configuration with a specific -// task. -message TaskPushNotificationConfig { - // Optional tenant - string tenant = 4; - - // The id of the config. - string id = 1 [(google.api.field_behavior) = REQUIRED]; - - // The id of the task this config is associated with. - string task_id = 3 [(google.api.field_behavior) = REQUIRED]; - - // The push notification configuration details. - PushNotificationConfig push_notification_config = 2 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:TaskPushNotificationConfig] - -// protolint:disable REPEATED_FIELD_NAMES_PLURALIZED -message StringList { - repeated string list = 1; -} -// protolint:enable REPEATED_FIELD_NAMES_PLURALIZED - -message SecurityRequirement { - map schemes = 1; -} - -// --8<-- [start:SecurityScheme] -// Defines a security scheme that can be used to secure an agent's endpoints. -// This is a discriminated union type based on the OpenAPI 3.2 Security Scheme Object. -// See: https://spec.openapis.org/oas/v3.2.0.html#security-scheme-object -message SecurityScheme { - oneof scheme { - // API key-based authentication. - APIKeySecurityScheme api_key_security_scheme = 1; - // HTTP authentication (Basic, Bearer, etc.). - HTTPAuthSecurityScheme http_auth_security_scheme = 2; - // OAuth 2.0 authentication. - OAuth2SecurityScheme oauth2_security_scheme = 3; - // OpenID Connect authentication. - OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; - // Mutual TLS authentication. - MutualTlsSecurityScheme mtls_security_scheme = 5; - } -} -// --8<-- [end:SecurityScheme] - -// --8<-- [start:APIKeySecurityScheme] -// Defines a security scheme using an API key. -message APIKeySecurityScheme { - // An optional description for the security scheme. - string description = 1; - // The location of the API key. Valid values are "query", "header", or "cookie". - string location = 2 [(google.api.field_behavior) = REQUIRED]; - // The name of the header, query, or cookie parameter to be used. - string name = 3 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:APIKeySecurityScheme] - -// --8<-- [start:HTTPAuthSecurityScheme] -// Defines a security scheme using HTTP authentication. -message HTTPAuthSecurityScheme { - // An optional description for the security scheme. - string description = 1; - // The name of the HTTP Authentication scheme to be used in the Authorization header, - // as defined in RFC7235 (e.g., "Bearer"). - // This value should be registered in the IANA Authentication Scheme registry. - string scheme = 2 [(google.api.field_behavior) = REQUIRED]; - // A hint to the client to identify how the bearer token is formatted (e.g., "JWT"). - // This is primarily for documentation purposes. - string bearer_format = 3; -} -// --8<-- [end:HTTPAuthSecurityScheme] - -// --8<-- [start:OAuth2SecurityScheme] -// Defines a security scheme using OAuth 2.0. -message OAuth2SecurityScheme { - // An optional description for the security scheme. - string description = 1; - // An object containing configuration information for the supported OAuth 2.0 flows. - OAuthFlows flows = 2 [(google.api.field_behavior) = REQUIRED]; - // URL to the oauth2 authorization server metadata - // RFC8414 (https://datatracker.ietf.org/doc/html/rfc8414). TLS is required. - string oauth2_metadata_url = 3; -} -// --8<-- [end:OAuth2SecurityScheme] - -// --8<-- [start:OpenIdConnectSecurityScheme] -// Defines a security scheme using OpenID Connect. -message OpenIdConnectSecurityScheme { - // An optional description for the security scheme. - string description = 1; - // The OpenID Connect Discovery URL for the OIDC provider's metadata. - // See: https://openid.net/specs/openid-connect-discovery-1_0.html - string open_id_connect_url = 2 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:OpenIdConnectSecurityScheme] - -// --8<-- [start:MutualTLSSecurityScheme] -// Defines a security scheme using mTLS authentication. -message MutualTlsSecurityScheme { - // An optional description for the security scheme. - string description = 1; -} -// --8<-- [end:MutualTLSSecurityScheme] - -// --8<-- [start:OAuthFlows] -// Defines the configuration for the supported OAuth 2.0 flows. -message OAuthFlows { - oneof flow { - // Configuration for the OAuth Authorization Code flow. - AuthorizationCodeOAuthFlow authorization_code = 1; - // Configuration for the OAuth Client Credentials flow. - ClientCredentialsOAuthFlow client_credentials = 2; - ImplicitOAuthFlow implicit = 3 [deprecated = true]; - PasswordOAuthFlow password = 4 [deprecated = true]; - // Configuration for the OAuth Device Code flow. - DeviceCodeOAuthFlow device_code = 5; - } -} -// --8<-- [end:OAuthFlows] - -// --8<-- [start:AuthorizationCodeOAuthFlow] -// Defines configuration details for the OAuth 2.0 Authorization Code flow. -message AuthorizationCodeOAuthFlow { - // The authorization URL to be used for this flow. - string authorization_url = 1 [(google.api.field_behavior) = REQUIRED]; - // The token URL to be used for this flow. - string token_url = 2 [(google.api.field_behavior) = REQUIRED]; - // The URL to be used for obtaining refresh tokens. - string refresh_url = 3; - // The available scopes for the OAuth2 security scheme. - map scopes = 4 [(google.api.field_behavior) = REQUIRED]; - // Indicates if PKCE (RFC 7636) is required for this flow. - // PKCE should always be used for public clients and is recommended for all clients. - bool pkce_required = 5; -} -// --8<-- [end:AuthorizationCodeOAuthFlow] - -// --8<-- [start:ClientCredentialsOAuthFlow] -// Defines configuration details for the OAuth 2.0 Client Credentials flow. -message ClientCredentialsOAuthFlow { - // The token URL to be used for this flow. - string token_url = 1 [(google.api.field_behavior) = REQUIRED]; - // The URL to be used for obtaining refresh tokens. - string refresh_url = 2; - // The available scopes for the OAuth2 security scheme. - map scopes = 3 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:ClientCredentialsOAuthFlow] - -// DEPRECATED -message ImplicitOAuthFlow { - // The authorization URL to be used for this flow. This MUST be in the - // form of a URL. The OAuth2 standard requires the use of TLS - string authorization_url = 1; - // The URL to be used for obtaining refresh tokens. This MUST be in the - // form of a URL. The OAuth2 standard requires the use of TLS. - string refresh_url = 2; - // The available scopes for the OAuth2 security scheme. A map between the - // scope name and a short description for it. The map MAY be empty. - map scopes = 3; -} - -// DEPRECATED -message PasswordOAuthFlow { - // The token URL to be used for this flow. This MUST be in the form of a URL. - // The OAuth2 standard requires the use of TLS. - string token_url = 1; - // The URL to be used for obtaining refresh tokens. This MUST be in the - // form of a URL. The OAuth2 standard requires the use of TLS. - string refresh_url = 2; - // The available scopes for the OAuth2 security scheme. A map between the - // scope name and a short description for it. The map MAY be empty. - map scopes = 3; -} - -// --8<-- [start:DeviceCodeOAuthFlow] -// Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628). -// This flow is designed for input-constrained devices such as IoT devices, -// and CLI tools where the user authenticates on a separate device. -message DeviceCodeOAuthFlow { - // The device authorization endpoint URL. - string device_authorization_url = 1 [(google.api.field_behavior) = REQUIRED]; - // The token URL to be used for this flow. - string token_url = 2 [(google.api.field_behavior) = REQUIRED]; - // The URL to be used for obtaining refresh tokens. - string refresh_url = 3; - // The available scopes for the OAuth2 security scheme. - map scopes = 4 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:DeviceCodeOAuthFlow] - -///////////// Request Messages /////////// -// --8<-- [start:SendMessageRequest] -// Represents a request for the `SendMessage` method. -message SendMessageRequest { - // Optional tenant, provided as a path parameter. - string tenant = 4; - // The message to send to the agent. - Message message = 1 [(google.api.field_behavior) = REQUIRED]; - // Configuration for the send request. - SendMessageConfiguration configuration = 2; - // A flexible key-value map for passing additional context or parameters. - google.protobuf.Struct metadata = 3; -} -// --8<-- [end:SendMessageRequest] - -// --8<-- [start:GetTaskRequest] -// Represents a request for the `GetTask` method. -message GetTaskRequest { - // Optional tenant, provided as a path parameter. - string tenant = 3; - // The resource id of the task. - string id = 1 [(google.api.field_behavior) = REQUIRED]; - // The maximum number of most recent messages from the task's history to retrieve. An - // unset value means the client does not impose any limit. A value of zero is - // a request to not include any messages. The server MUST NOT return more - // messages than the provided value, but MAY apply a lower limit. - optional int32 history_length = 2; -} -// --8<-- [end:GetTaskRequest] - -// --8<-- [start:ListTasksRequest] -// Parameters for listing tasks with optional filtering criteria. -message ListTasksRequest { - // Optional tenant, provided as a path parameter. - string tenant = 9; - // Filter tasks by context ID to get tasks from a specific conversation or session. - string context_id = 1; - // Filter tasks by their current status state. - TaskState status = 2; - // Maximum number of tasks to return. Must be between 1 and 100. - // Defaults to 50 if not specified. - optional int32 page_size = 3; - // Token for pagination. Use the next_page_token from a previous ListTasksResponse. - string page_token = 4; - // The maximum number of messages to include in each task's history. - optional int32 history_length = 5; - // Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z"). - // Only tasks with a status timestamp time greater than or equal to this value will be returned. - google.protobuf.Timestamp status_timestamp_after = 6; - // Whether to include artifacts in the returned tasks. - // Defaults to false to reduce payload size. - optional bool include_artifacts = 7; -} -// --8<-- [end:ListTasksRequest] - -// --8<-- [start:ListTasksResponse] -// Result object for tasks/list method containing an array of tasks and pagination information. -message ListTasksResponse { - // Array of tasks matching the specified criteria. - repeated Task tasks = 1 [(google.api.field_behavior) = REQUIRED]; - // Token for retrieving the next page. Empty string if no more results. - string next_page_token = 2 [(google.api.field_behavior) = REQUIRED]; - // The size of page requested. - int32 page_size = 3 [(google.api.field_behavior) = REQUIRED]; - // Total number of tasks available (before pagination). - int32 total_size = 4 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:ListTasksResponse] - -// --8<-- [start:CancelTaskRequest] -// Represents a request for the `CancelTask` method. -message CancelTaskRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The resource id of the task to cancel. - string id = 1 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:CancelTaskRequest] - -// --8<-- [start:GetTaskPushNotificationConfigRequest] -message GetTaskPushNotificationConfigRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The parent task resource id. - string task_id = 3 [(google.api.field_behavior) = REQUIRED]; - // The resource id of the config to retrieve. - string id = 1 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:GetTaskPushNotificationConfigRequest] - -// --8<-- [start:DeleteTaskPushNotificationConfigRequest] -// Represents a request for the `DeleteTaskPushNotificationConfig` method. -message DeleteTaskPushNotificationConfigRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The parent task resource id. - string task_id = 3 [(google.api.field_behavior) = REQUIRED]; - // The resource id of the config to delete. - string id = 1 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:DeleteTaskPushNotificationConfigRequest] - -// --8<-- [start:CreateTaskPushNotificationConfigRequest] -// Represents a request for the `CreateTaskPushNotificationConfig` method. -message CreateTaskPushNotificationConfigRequest { - reserved 3; - // Optional tenant, provided as a path parameter. - string tenant = 4; - // The parent task resource id. - string task_id = 1 [(google.api.field_behavior) = REQUIRED]; - // The ID for the new config. - string config_id = 2 [(google.api.field_behavior) = REQUIRED]; - // The configuration to create. - PushNotificationConfig config = 5 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:CreateTaskPushNotificationConfigRequest] - -// --8<-- [start:SubscribeToTaskRequest] -message SubscribeToTaskRequest { - // Optional tenant, provided as a path parameter. - string tenant = 2; - // The resource id of the task to subscribe to. - string id = 1 [(google.api.field_behavior) = REQUIRED]; -} -// --8<-- [end:SubscribeToTaskRequest] - -// --8<-- [start:ListTaskPushNotificationConfigRequest] -message ListTaskPushNotificationConfigRequest { - // Optional tenant, provided as a path parameter. - string tenant = 4; - // The parent task resource id. - string task_id = 1 [(google.api.field_behavior) = REQUIRED]; - - // The maximum number of configurations to return. - int32 page_size = 2; - - // A page token received from a previous ListTaskPushNotificationConfigRequest call. - string page_token = 3; -} -// --8<-- [end:ListTaskPushNotificationConfigRequest] - -// --8<-- [start:GetExtendedAgentCardRequest] -message GetExtendedAgentCardRequest { - // Optional tenant, provided as a path parameter. - string tenant = 1; -} -// --8<-- [end:GetExtendedAgentCardRequest] - -//////// Response Messages /////////// -// --8<-- [start:SendMessageResponse] -message SendMessageResponse { - oneof payload { - Task task = 1; - Message message = 2; - } -} -// --8<-- [end:SendMessageResponse] - -// --8<-- [start:StreamResponse] -// A wrapper object used in streaming operations to encapsulate different types of response data. -message StreamResponse { - oneof payload { - // A Task object containing the current state of the task. - Task task = 1; - // A Message object containing a message from the agent. - Message message = 2; - // An event indicating a task status update. - TaskStatusUpdateEvent status_update = 3; - // An event indicating a task artifact update. - TaskArtifactUpdateEvent artifact_update = 4; - } -} -// --8<-- [end:StreamResponse] - -// --8<-- [start:ListTaskPushNotificationConfigResponse] -// Represents a successful response for the `ListTaskPushNotificationConfig` -// method. -message ListTaskPushNotificationConfigResponse { - // The list of push notification configurations. - repeated TaskPushNotificationConfig configs = 1; - // A token, which can be sent as `page_token` to retrieve the next page. - // If this field is omitted, there are no subsequent pages. - string next_page_token = 2; -} -// --8<-- [end:ListTaskPushNotificationConfigResponse] diff --git a/spec-grpc/src/main/resources/META-INF/beans.xml b/spec-grpc/src/main/resources/META-INF/beans.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java b/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java deleted file mode 100644 index 67b2a0ffd..000000000 --- a/spec-grpc/src/test/java/io/a2a/grpc/mapper/A2ACommonFieldMapperTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package io.a2a.grpc.mapper; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.util.Map; - -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.util.JsonFormat; - -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.spec.MessageSendParams; -import org.junit.jupiter.api.Test; - -public class A2ACommonFieldMapperTest { - - /** - * Test that valueToObject handles empty struct correctly without throwing NullPointerException. - * - * This test verifies the fix for the bug where an empty struct in the JSON - * (e.g., "response": {}) would cause a NullPointerException because structToMap - * returns null for empty structs. - */ - @Test - void testValueToObject_WithEmptyStruct_ReturnsEmptyMap() throws InvalidProtocolBufferException { - // JSON containing an empty struct in "response" field - String json = "{\n" + - " \"message\": {\n" + - " \"messageId\": \"b3b1ab58-c3d0-4e6d-9e47-9d8a12fe0809\",\n" + - " \"role\": \"ROLE_USER\",\n" + - " \"parts\": [{\n" + - " \"text\": \"Hello\"\n" + - " }, {\n" + - " \"data\": {\n" + - " \"data\": {\n" + - " \"id\": \"call_94yo5ymj3qi5glbpkw5eicfd\",\n" + - " \"args\": {\n" + - " \"agent_name\": \"Default Agent\"\n" + - " },\n" + - " \"name\": \"transfer_to_agent\"\n" + - " }\n" + - " }\n" + - " }, {\n" + - " \"data\": {\n" + - " \"data\": {\n" + - " \"response\": {\n" + - " },\n" + - " \"id\": \"call_94yo5ymj3qi5glbpkw5eicfd\",\n" + - " \"name\": \"transfer_to_agent\"\n" + - " }\n" + - " }\n" + - " }, {\n" + - " \"text\": \"World\"\n" + - " }],\n" + - " \"metadata\": {\n" + - " }\n" + - " },\n" + - " \"configuration\": {\n" + - " \"blocking\": true\n" + - " },\n" + - " \"metadata\": {\n" + - " }\n" + - "}"; - - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); - JsonFormat.parser().merge(json, builder); - - // This should not throw NullPointerException - MessageSendParams messageSendParams = ProtoUtils.FromProto.messageSendParams(builder); - - assertNotNull(messageSendParams); - assertNotNull(messageSendParams.message()); - assertEquals(4, messageSendParams.message().parts().size()); - } - - /** - * Test that valueToObject handles nested empty struct correctly. - */ - @Test - void testValueToObject_WithNestedEmptyStruct_ReturnsEmptyMap() throws InvalidProtocolBufferException { - String json = "{\n" + - " \"message\": {\n" + - " \"messageId\": \"test-id\",\n" + - " \"role\": \"ROLE_USER\",\n" + - " \"parts\": [{\n" + - " \"data\": {\n" + - " \"data\": {\n" + - " \"nested\": {\n" + - " \"empty\": {\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }]\n" + - " }\n" + - "}"; - - io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); - JsonFormat.parser().merge(json, builder); - - // This should not throw NullPointerException - MessageSendParams messageSendParams = ProtoUtils.FromProto.messageSendParams(builder); - - assertNotNull(messageSendParams); - assertNotNull(messageSendParams.message()); - } -} diff --git a/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java b/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java deleted file mode 100644 index 99ff1ad39..000000000 --- a/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java +++ /dev/null @@ -1,272 +0,0 @@ -package io.a2a.grpc.mapper; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.util.Collections; - -import io.a2a.spec.Artifact; -import io.a2a.spec.Message; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; - -public class StreamResponseMapperTest { - - @Test - void testConvertTask_ToProto() { - // Arrange - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(task); - - // Assert - assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.TASK, result.getPayloadCase()); - assertEquals("task-123", result.getTask().getId()); - assertEquals("context-456", result.getTask().getContextId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_COMPLETED, result.getTask().getStatus().getState()); - } - - @Test - void testConvertTask_FromProto() { - // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setTask(io.a2a.grpc.Task.newBuilder() - .setId("task-123") - .setContextId("context-456") - .setStatus(io.a2a.grpc.TaskStatus.newBuilder() - .setState(io.a2a.grpc.TaskState.TASK_STATE_COMPLETED) - .build()) - .build()) - .build(); - - // Act - StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); - - // Assert - assertNotNull(result); - assertInstanceOf(Task.class, result); - Task task = (Task) result; - assertEquals("task-123", task.id()); - assertEquals("context-456", task.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, task.status().state()); - } - - @Test - void testConvertMessage_ToProto() { - // Arrange - Message message = Message.builder() - .messageId("msg-123") - .contextId("context-456") - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("Hello"))) - .build(); - - // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(message); - - // Assert - assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.MESSAGE, result.getPayloadCase()); - assertEquals("msg-123", result.getMessage().getMessageId()); - assertEquals("context-456", result.getMessage().getContextId()); - assertEquals(io.a2a.grpc.Role.ROLE_USER, result.getMessage().getRole()); - } - - @Test - void testConvertMessage_FromProto() { - // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setMessage(io.a2a.grpc.Message.newBuilder() - .setMessageId("msg-123") - .setContextId("context-456") - .setRole(io.a2a.grpc.Role.ROLE_USER) - .addParts(io.a2a.grpc.Part.newBuilder() - .setText("Hello") - .build()) - .build()) - .build(); - - // Act - StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); - - // Assert - assertNotNull(result); - assertInstanceOf(Message.class, result); - Message message = (Message) result; - assertEquals("msg-123", message.messageId()); - assertEquals("context-456", message.contextId()); - assertEquals(Message.Role.ROLE_USER, message.role()); - } - - @Test - void testConvertTaskStatusUpdateEvent_ToProto() { - // Arrange - TaskStatusUpdateEvent event = TaskStatusUpdateEvent.builder() - .taskId("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(event); - - // Assert - assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.STATUS_UPDATE, result.getPayloadCase()); - assertEquals("task-123", result.getStatusUpdate().getTaskId()); - assertEquals("context-456", result.getStatusUpdate().getContextId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_WORKING, result.getStatusUpdate().getStatus().getState()); - } - - @Test - void testConvertTaskStatusUpdateEvent_FromProto() { - // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setStatusUpdate(io.a2a.grpc.TaskStatusUpdateEvent.newBuilder() - .setTaskId("task-123") - .setContextId("context-456") - .setStatus(io.a2a.grpc.TaskStatus.newBuilder() - .setState(io.a2a.grpc.TaskState.TASK_STATE_WORKING) - .build()) - .build()) - .build(); - - // Act - StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); - - // Assert - assertNotNull(result); - assertInstanceOf(TaskStatusUpdateEvent.class, result); - TaskStatusUpdateEvent event = (TaskStatusUpdateEvent) result; - assertEquals("task-123", event.taskId()); - assertEquals("context-456", event.contextId()); - assertEquals(TaskState.TASK_STATE_WORKING, event.status().state()); - assertEquals(false, event.isFinal()); - } - - @Test - void testConvertTaskArtifactUpdateEvent_ToProto() { - // Arrange - TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder() - .taskId("task-123") - .contextId("context-456") - .artifact(Artifact.builder() - .artifactId("artifact-1") - .name("result") - .parts(new TextPart("Result text")) - .build()) - .build(); - - // Act - io.a2a.grpc.StreamResponse result = StreamResponseMapper.INSTANCE.toProto(event); - - // Assert - assertNotNull(result); - assertEquals(io.a2a.grpc.StreamResponse.PayloadCase.ARTIFACT_UPDATE, result.getPayloadCase()); - assertEquals("task-123", result.getArtifactUpdate().getTaskId()); - assertEquals("context-456", result.getArtifactUpdate().getContextId()); - assertEquals("artifact-1", result.getArtifactUpdate().getArtifact().getArtifactId()); - assertEquals("result", result.getArtifactUpdate().getArtifact().getName()); - } - - @Test - void testConvertTaskArtifactUpdateEvent_FromProto() { - // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder() - .setArtifactUpdate(io.a2a.grpc.TaskArtifactUpdateEvent.newBuilder() - .setTaskId("task-123") - .setContextId("context-456") - .setArtifact(io.a2a.grpc.Artifact.newBuilder() - .setArtifactId("artifact-1") - .setName("result") - .addParts(io.a2a.grpc.Part.newBuilder() - .setText("Result text") - .build()) - .build()) - .build()) - .build(); - - // Act - StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); - - // Assert - assertNotNull(result); - assertInstanceOf(TaskArtifactUpdateEvent.class, result); - TaskArtifactUpdateEvent event = (TaskArtifactUpdateEvent) result; - assertEquals("task-123", event.taskId()); - assertEquals("context-456", event.contextId()); - assertEquals("artifact-1", event.artifact().artifactId()); - assertEquals("result", event.artifact().name()); - } - - @Test - void testConvertStreamResponse_FromProto_PayloadNotSet_ThrowsException() { - // Arrange - io.a2a.grpc.StreamResponse proto = io.a2a.grpc.StreamResponse.newBuilder().build(); - - // Act & Assert - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - StreamResponseMapper.INSTANCE.fromProto(proto); - }); - assertEquals("StreamResponse payload oneof field not set", exception.getMessage()); - } - - @Test - void testConvertStreamResponse_Roundtrip_Task() { - // Arrange - Task originalTask = Task.builder() - .id("task-123") - .contextId("context-456") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - // Act - io.a2a.grpc.StreamResponse proto = StreamResponseMapper.INSTANCE.toProto(originalTask); - StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); - - // Assert - assertNotNull(result); - assertInstanceOf(Task.class, result); - Task roundtrippedTask = (Task) result; - assertEquals(originalTask.id(), roundtrippedTask.id()); - assertEquals(originalTask.contextId(), roundtrippedTask.contextId()); - assertEquals(originalTask.status().state(), roundtrippedTask.status().state()); - } - - @Test - void testConvertStreamResponse_Roundtrip_Message() { - // Arrange - Message originalMessage = Message.builder() - .messageId("msg-123") - .contextId("context-456") - .role(Message.Role.ROLE_AGENT) - .parts(Collections.singletonList(new TextPart("Response"))) - .build(); - - // Act - io.a2a.grpc.StreamResponse proto = StreamResponseMapper.INSTANCE.toProto(originalMessage); - StreamingEventKind result = StreamResponseMapper.INSTANCE.fromProto(proto); - - // Assert - assertNotNull(result); - assertInstanceOf(Message.class, result); - Message roundtrippedMessage = (Message) result; - assertEquals(originalMessage.messageId(), roundtrippedMessage.messageId()); - assertEquals(originalMessage.contextId(), roundtrippedMessage.contextId()); - assertEquals(originalMessage.role(), roundtrippedMessage.role()); - } -} diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java deleted file mode 100644 index 569d77981..000000000 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java +++ /dev/null @@ -1,414 +0,0 @@ -package io.a2a.grpc.utils; - -import static io.a2a.grpc.utils.JSONRPCUtils.ERROR_MESSAGE; -import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; - -import com.google.gson.JsonSyntaxException; - -import io.a2a.grpc.Role; -import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; -import io.a2a.jsonrpc.common.json.JsonMappingException; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.wrappers.A2ARequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.Message; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.TaskPushNotificationConfig; -import org.junit.jupiter.api.Test; - -public class JSONRPCUtilsTest { - - @Test - public void testParseCreateTaskPushNotificationConfigRequest_ValidProtoFormat() throws JsonProcessingException { - String validRequest = """ - { - "jsonrpc": "2.0", - "method": "CreateTaskPushNotificationConfig", - "id": "1", - "params": { - "taskId": "task-123", - "configId": "config-456", - "tenant": "", - "config": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - } - } - """; - - A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest, null); - - assertNotNull(request); - assertInstanceOf(CreateTaskPushNotificationConfigRequest.class, request); - CreateTaskPushNotificationConfigRequest setRequest = (CreateTaskPushNotificationConfigRequest) request; - assertEquals("2.0", setRequest.getJsonrpc()); - assertEquals(1, setRequest.getId()); - assertEquals("CreateTaskPushNotificationConfig", setRequest.getMethod()); - - TaskPushNotificationConfig config = setRequest.getParams(); - assertNotNull(config); - assertEquals("task-123", config.taskId()); - assertNotNull(config.config()); - assertEquals("https://example.com/callback", config.config().url()); - } - - @Test - public void testParseGetTaskPushNotificationConfigRequest_ValidProtoFormat() throws JsonProcessingException { - String validRequest = """ - { - "jsonrpc": "2.0", - "method": "GetTaskPushNotificationConfig", - "id": "2", - "params": { - "taskId": "task-123", - "id": "config-456" - } - } - """; - - A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest, null); - - assertNotNull(request); - assertInstanceOf(GetTaskPushNotificationConfigRequest.class, request); - GetTaskPushNotificationConfigRequest getRequest = (GetTaskPushNotificationConfigRequest) request; - assertEquals("2.0", getRequest.getJsonrpc()); - assertEquals(2, getRequest.getId()); - assertEquals("GetTaskPushNotificationConfig", getRequest.getMethod()); - assertNotNull(getRequest.getParams()); - assertEquals("task-123", getRequest.getParams().taskId()); - } - - @Test - public void testParseMalformedJSON_ThrowsJsonSyntaxException() { - String malformedRequest = """ - { - "jsonrpc": "2.0", - "method": "CreateTaskPushNotificationConfig", - "params": { - "parent": "tasks/task-123" - """; // Missing closing braces - - JsonSyntaxException exception = assertThrows(JsonSyntaxException.class, () -> { - JSONRPCUtils.parseRequestBody(malformedRequest, null); - }); - assertEquals("java.io.EOFException: End of input at line 6 column 1 path $.params.parent", exception.getMessage()); - } - - @Test - public void testParseInvalidParams_ThrowsInvalidParamsJsonMappingException() { - String invalidParamsRequest = """ - { - "jsonrpc": "2.0", - "method": "CreateTaskPushNotificationConfig", - "id": "3", - "params": "not_a_dict" - } - """; - - InvalidParamsJsonMappingException exception = assertThrows( - InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(invalidParamsRequest, null) - ); - assertEquals(3, exception.getId()); - } - - @Test - public void testParseInvalidProtoStructure_ThrowsInvalidParamsJsonMappingException() { - String invalidStructure = """ - { - "jsonrpc": "2.0", - "method": "CreateTaskPushNotificationConfig", - "id": "4", - "params": { - "invalid_field": "value" - } - } - """; - - InvalidParamsJsonMappingException exception = assertThrows( - InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(invalidStructure, null) - ); - assertEquals(4, exception.getId()); - assertEquals(ERROR_MESSAGE.formatted("invalid_field in message a2a.v1.CreateTaskPushNotificationConfigRequest"), exception.getMessage()); - } - - @Test - public void testParseNumericalTimestampThrowsInvalidParamsJsonMappingException() { - String valideRequest = """ - { - "jsonrpc": "2.0", - "method": "ListTasks", - "id": "1", - "params": { - "statusTimestampAfter": "2023-10-27T10:00:00Z" - } - } - """; - String invalidRequest = """ - { - "jsonrpc": "2.0", - "method": "ListTasks", - "id": "2", - "params": { - "statusTimestampAfter": "1" - } - } - """; - - try { - A2ARequest request = JSONRPCUtils.parseRequestBody(valideRequest, null); - assertEquals(1, request.getId()); - } catch (JsonProcessingException e) { - fail(e); - } - InvalidParamsJsonMappingException exception = assertThrows( - InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(invalidRequest, null) - ); - assertEquals(2, exception.getId()); - } - - @Test - public void testParseMissingField_ThrowsInvalidParamsError() throws JsonMappingException { - String missingRoleMessage= """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "id": "18", - "params":{ - "message":{ - "messageId":"message-1234", - "contextId":"context-1234", - "parts":[ - { - "text":"tell me a joke" - } - ], - "metadata":{ - - } - } - } - }"""; - InvalidParamsJsonMappingException exception = assertThrows( - InvalidParamsJsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(missingRoleMessage, null) - ); - assertEquals(18, exception.getId()); - } - - @Test - public void testParseUnknownField_ThrowsJsonMappingException() throws JsonMappingException { - String unkownFieldMessage= """ - { - "jsonrpc":"2.0", - "method":"SendMessage", - "id": "18", - "params":{ - "message":{ - "role": "ROLE_AGENT", - "unknown":"field", - "messageId":"message-1234", - "contextId":"context-1234", - "parts":[ - { - "text":"tell me a joke" - } - ], - "metadata":{ - - } - } - } - }"""; - JsonMappingException exception = assertThrows( - JsonMappingException.class, - () -> JSONRPCUtils.parseRequestBody(unkownFieldMessage, null) - ); - assertEquals(ERROR_MESSAGE.formatted("unknown in message a2a.v1.Message"), exception.getMessage()); - } - - @Test - public void testParseInvalidTypeWithNullId_UsesEmptyStringSentinel() throws Exception { - // Test the low-level convertProtoBufExceptionToJsonProcessingException with null ID - // This tests the sentinel value logic directly - com.google.protobuf.InvalidProtocolBufferException protoException = - new com.google.protobuf.InvalidProtocolBufferException("Expected ENUM but found \"INVALID_VALUE\""); - - // Use reflection to call the private method for testing - java.lang.reflect.Method method = JSONRPCUtils.class.getDeclaredMethod( - "convertProtoBufExceptionToJsonProcessingException", - com.google.protobuf.InvalidProtocolBufferException.class, - Object.class - ); - method.setAccessible(true); - - JsonProcessingException exception = (JsonProcessingException) method.invoke( - null, - protoException, - null // null ID - ); - - // Should be InvalidParamsJsonMappingException with empty string sentinel - assertInstanceOf(InvalidParamsJsonMappingException.class, exception, - "Expected InvalidParamsJsonMappingException for proto error"); - InvalidParamsJsonMappingException invalidParamsException = (InvalidParamsJsonMappingException) exception; - assertEquals("", invalidParamsException.getId(), - "Expected empty string sentinel when ID is null"); - } - - @Test - public void testParseInvalidTypeWithValidId_PreservesId() throws Exception { - // Test the low-level convertProtoBufExceptionToJsonProcessingException with valid ID - com.google.protobuf.InvalidProtocolBufferException protoException = - new com.google.protobuf.InvalidProtocolBufferException("Expected ENUM but found \"INVALID_VALUE\""); - - // Use reflection to call the private method for testing - java.lang.reflect.Method method = JSONRPCUtils.class.getDeclaredMethod( - "convertProtoBufExceptionToJsonProcessingException", - com.google.protobuf.InvalidProtocolBufferException.class, - Object.class - ); - method.setAccessible(true); - - JsonProcessingException exception = (JsonProcessingException) method.invoke( - null, - protoException, - 42 // Valid ID - ); - - // Should be InvalidParamsJsonMappingException with preserved ID - assertInstanceOf(InvalidParamsJsonMappingException.class, exception, - "Expected InvalidParamsJsonMappingException for proto error"); - InvalidParamsJsonMappingException invalidParamsException = (InvalidParamsJsonMappingException) exception; - assertEquals(42, invalidParamsException.getId(), - "Expected actual ID to be preserved when present"); - } - - @Test - public void testGenerateCreateTaskPushNotificationConfigResponse_Success() throws Exception { - TaskPushNotificationConfig config = new TaskPushNotificationConfig( - "task-123", - PushNotificationConfig.builder() - .url("https://example.com/callback") - .id("config-456") - .build(), - "tenant" - ); - - String responseJson = """ - { - "jsonrpc": "2.0", - "id": "1", - "result": { - "taskId": "task-123", - "id": "config-456", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "id": "config-456" - } - } - } - """; - - CreateTaskPushNotificationConfigResponse response = - (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - assertNotNull(response); - assertEquals(1, response.getId()); - assertNotNull(response.getResult()); - assertEquals("task-123", response.getResult().taskId()); - assertEquals("https://example.com/callback", response.getResult().config().url()); - } - - @Test - public void testGenerateGetTaskPushNotificationConfigResponse_Success() throws Exception { - String responseJson = """ - { - "jsonrpc": "2.0", - "id": "2", - "result": { - "taskId": "task-123", - "id": "config-456", - "pushNotificationConfig": { - "url": "https://example.com/callback", - "id": "config-456" - } - } - } - """; - - GetTaskPushNotificationConfigResponse response = - (GetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - assertNotNull(response); - assertEquals(2, response.getId()); - assertNotNull(response.getResult()); - assertEquals("task-123", response.getResult().taskId()); - assertEquals("https://example.com/callback", response.getResult().config().url()); - } - - @Test - public void testParseErrorResponse_InvalidParams() throws Exception { - String errorResponse = """ - { - "jsonrpc": "2.0", - "id": "5", - "error": { - "code": -32602, - "message": "Invalid params" - } - } - """; - - CreateTaskPushNotificationConfigResponse response = - (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - assertNotNull(response); - assertEquals(5, response.getId()); - assertNotNull(response.getError()); - assertInstanceOf(InvalidParamsError.class, response.getError()); - assertEquals(-32602, response.getError().getCode()); - assertEquals("Invalid params", response.getError().getMessage()); - } - - @Test - public void testParseErrorResponse_ParseError() throws Exception { - String errorResponse = """ - { - "jsonrpc": "2.0", - "id": 6, - "error": { - "code": -32700, - "message": "Parse error" - } - } - """; - - CreateTaskPushNotificationConfigResponse response = - (CreateTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - assertNotNull(response); - assertEquals(6, response.getId()); - assertNotNull(response.getError()); - assertInstanceOf(JSONParseError.class, response.getError()); - assertEquals(-32700, response.getError().getCode()); - assertEquals("Parse error", response.getError().getMessage()); - } -} diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java deleted file mode 100644 index b857cb6b1..000000000 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/ToProtoTest.java +++ /dev/null @@ -1,344 +0,0 @@ -package io.a2a.grpc.utils; - -import static io.a2a.grpc.Role.ROLE_AGENT; -import static io.a2a.grpc.Role.ROLE_USER; -import static io.a2a.spec.AgentInterface.CURRENT_PROTOCOL_VERSION; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.time.OffsetDateTime; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import io.a2a.grpc.SendMessageConfiguration; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.SecurityRequirement; -import io.a2a.spec.Artifact; -import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.HTTPAuthSecurityScheme; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; - -public class ToProtoTest { - - private static final Message SIMPLE_MESSAGE = Message.builder() - .role(Message.Role.ROLE_USER) - .parts(Collections.singletonList(new TextPart("tell me a joke"))) - .contextId("context-1234") - .messageId("message-1234") - .build(); - - @Test - public void convertAgentCard() { - AgentCard agentCard = AgentCard.builder() - .name("Hello World Agent") - .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999", "", "123"))) - .version("1.0.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(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(); - io.a2a.grpc.AgentCard result = ProtoUtils.ToProto.agentCard(agentCard); - assertEquals("Hello World Agent", result.getName()); - assertEquals("Just a hello world agent", result.getDescription()); - assertEquals(1, result.getSupportedInterfacesList().size()); - assertEquals("http://localhost:9999", result.getSupportedInterfacesList().get(0).getUrl()); - assertEquals("jsonrpc", result.getSupportedInterfacesList().get(0).getProtocolBinding()); - assertEquals("123", result.getSupportedInterfacesList().get(0).getProtocolVersion()); - assertEquals("1.0.0", result.getVersion()); - assertEquals("http://example.com/docs", result.getDocumentationUrl()); - assertEquals(1, result.getDefaultInputModesCount()); - assertEquals("text", result.getDefaultInputModes(0)); - assertEquals(1, result.getDefaultOutputModesCount()); - assertEquals("text", result.getDefaultOutputModes(0)); - // protocolVersion is now in AgentInterface - agentCard = AgentCard.builder() - .name("Hello World Agent") - .description("Just a hello world agent") - .supportedInterfaces(Collections.singletonList(new AgentInterface("jsonrpc", "http://localhost:9999"))) - .version("1.0.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(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())) - // .iconUrl("http://example.com/icon.svg") - .securitySchemes(Map.of("basic", HTTPAuthSecurityScheme.builder().scheme("basic").description("Basic Auth").build())) - .securityRequirements(List.of(SecurityRequirement.builder() - .scheme("oauth", - List.of("read")) - .build())) - .build(); - result = ProtoUtils.ToProto.agentCard(agentCard); - assertEquals("Hello World Agent", result.getName()); - assertEquals("Just a hello world agent", result.getDescription()); - assertEquals(1, result.getSupportedInterfacesList().size()); - assertEquals("http://localhost:9999", result.getSupportedInterfacesList().get(0).getUrl()); - assertEquals("jsonrpc", result.getSupportedInterfacesList().get(0).getProtocolBinding()); - assertEquals(CURRENT_PROTOCOL_VERSION, result.getSupportedInterfacesList().get(0).getProtocolVersion()); - assertEquals("1.0.0", result.getVersion()); - assertEquals("http://example.com/docs", result.getDocumentationUrl()); - assertEquals(1, result.getDefaultInputModesCount()); - assertEquals("text", result.getDefaultInputModes(0)); - assertEquals(1, result.getDefaultOutputModesCount()); - assertEquals("text", result.getDefaultOutputModes(0)); - // protocolVersions field has been removed from the proto - assertEquals(1, result.getSecurityRequirementsCount()); - assertEquals(1, result.getSecurityRequirements(0).getSchemesMap().size()); - assertEquals(true, result.getSecurityRequirements(0).getSchemesMap().containsKey("oauth")); - assertEquals(1, result.getSecurityRequirements(0).getSchemesMap().get("oauth").getListCount()); - assertEquals("read", result.getSecurityRequirements(0).getSchemesMap().get("oauth").getList(0)); - assertEquals(1, result.getSecuritySchemesMap().size()); - assertEquals(true, result.getSecuritySchemesMap().containsKey("basic")); - assertEquals(result.getSecuritySchemesMap().get("basic").getApiKeySecurityScheme().getDefaultInstanceForType(), result.getSecuritySchemesMap().get("basic").getApiKeySecurityScheme()); - assertEquals(result.getSecuritySchemesMap().get("basic").getOauth2SecurityScheme().getDefaultInstanceForType(), result.getSecuritySchemesMap().get("basic").getOauth2SecurityScheme()); - assertEquals("basic", result.getSecuritySchemesMap().get("basic").getHttpAuthSecurityScheme().getScheme()); - assertEquals("Basic Auth", result.getSecuritySchemesMap().get("basic").getHttpAuthSecurityScheme().getDescription()); - } - - @Test - public void convertTask() { - Task task = Task.builder().id("cancel-task-123") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - io.a2a.grpc.Task result = ProtoUtils.ToProto.task(task); - assertEquals("session-xyz", result.getContextId()); - assertEquals("cancel-task-123", result.getId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); - assertEquals(0, result.getArtifactsCount()); - assertEquals(0, result.getHistoryCount()); - task = Task.builder().id("cancel-task-123") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .artifacts(List.of(Artifact.builder() - .artifactId("11") - .name("artefact") - .parts(new TextPart("text")) - .build())) - .history(List.of(SIMPLE_MESSAGE)) - .metadata(Collections.emptyMap()) - .build(); - result = ProtoUtils.ToProto.task(task); - assertEquals("session-xyz", result.getContextId()); - assertEquals("cancel-task-123", result.getId()); - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_SUBMITTED, result.getStatus().getState()); - assertEquals(1, result.getArtifactsCount()); - assertEquals("11", result.getArtifacts(0).getArtifactId()); - assertEquals("artefact", result.getArtifacts(0).getName()); - assertEquals(1, result.getArtifacts(0).getPartsCount()); - assertEquals(true, result.getArtifacts(0).getParts(0).hasText()); - assertEquals(false, result.getArtifacts(0).getParts(0).hasRaw()); - assertEquals(false, result.getArtifacts(0).getParts(0).hasUrl()); - assertEquals(false, result.getArtifacts(0).getParts(0).hasData()); - assertEquals("text", result.getArtifacts(0).getParts(0).getText()); - assertEquals(1, result.getHistoryCount()); - assertEquals("context-1234", result.getHistory(0).getContextId()); - assertEquals("message-1234", result.getHistory(0).getMessageId()); - assertEquals(ROLE_USER, result.getHistory(0).getRole()); - assertEquals(1, result.getHistory(0).getPartsCount()); - assertEquals("tell me a joke", result.getHistory(0).getParts(0).getText()); - assertEquals(false, result.getHistory(0).getParts(0).hasRaw()); - assertEquals(false, result.getHistory(0).getParts(0).hasUrl()); - assertEquals(false, result.getHistory(0).getParts(0).hasData()); - } - - @Test - public void convertMessage() { - io.a2a.grpc.Message result = ProtoUtils.ToProto.message(SIMPLE_MESSAGE); - assertEquals("context-1234", result.getContextId()); - assertEquals("message-1234", result.getMessageId()); - assertEquals(ROLE_USER, result.getRole()); - assertEquals(1, result.getPartsCount()); - assertEquals("tell me a joke", result.getParts(0).getText()); - assertEquals(false, result.getParts(0).hasRaw()); - assertEquals(false, result.getParts(0).hasUrl()); - assertEquals(false, result.getParts(0).hasData()); - Message message = Message.builder() - .role(Message.Role.ROLE_AGENT) - .parts(Collections.singletonList(new TextPart("tell me a joke"))) - .messageId("message-1234") - .build(); - result = ProtoUtils.ToProto.message(message); - assertEquals("", result.getContextId()); - assertEquals("message-1234", result.getMessageId()); - assertEquals(ROLE_AGENT, result.getRole()); - assertEquals(1, result.getPartsCount()); - assertEquals("tell me a joke", result.getParts(0).getText()); - assertEquals(false, result.getParts(0).hasRaw()); - assertEquals(false, result.getParts(0).hasUrl()); - assertEquals(false, result.getParts(0).hasData()); - } - - @Test - public void convertTaskPushNotificationConfig() { - TaskPushNotificationConfig taskPushConfig = new TaskPushNotificationConfig("push-task-123", - PushNotificationConfig.builder() - .url("http://example.com") - .id("xyz") - .build(), null); - io.a2a.grpc.TaskPushNotificationConfig result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); - assertEquals("push-task-123", result.getTaskId()); - assertEquals("xyz", result.getId()); - assertNotNull(result.getPushNotificationConfig()); - assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); - assertEquals("xyz", result.getPushNotificationConfig().getId()); - assertEquals(false, result.getPushNotificationConfig().hasAuthentication()); - taskPushConfig - = new TaskPushNotificationConfig("push-task-123", - PushNotificationConfig.builder() - .token("AAAAAA") - .authentication(new AuthenticationInfo("jwt", "credentials")) - .url("http://example.com") - .id("xyz") - .build(), null); - result = ProtoUtils.ToProto.taskPushNotificationConfig(taskPushConfig); - assertEquals("push-task-123", result.getTaskId()); - assertEquals("xyz", result.getId()); - assertNotNull(result.getPushNotificationConfig()); - assertEquals("http://example.com", result.getPushNotificationConfig().getUrl()); - assertEquals("xyz", result.getPushNotificationConfig().getId()); - assertEquals("AAAAAA", result.getPushNotificationConfig().getToken()); - assertEquals(true, result.getPushNotificationConfig().hasAuthentication()); - assertEquals("credentials", result.getPushNotificationConfig().getAuthentication().getCredentials()); - assertEquals("jwt", result.getPushNotificationConfig().getAuthentication().getScheme()); - } - - @Test - public void convertTaskArtifactUpdateEvent() { - TaskArtifactUpdateEvent task = TaskArtifactUpdateEvent.builder() - .taskId("task-123") - .contextId("session-123") - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()).build(); - io.a2a.grpc.TaskArtifactUpdateEvent result = ProtoUtils.ToProto.taskArtifactUpdateEvent(task); - assertEquals("task-123", result.getTaskId()); - assertEquals("session-123", result.getContextId()); - assertNotNull(result.getArtifact()); - assertEquals("11", result.getArtifact().getArtifactId()); - assertEquals(1, result.getArtifact().getPartsCount()); - assertEquals("text", result.getArtifact().getParts(0).getText()); - } - - @Test - public void convertTaskStatusUpdateEvent() { - TaskStatus completedStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED); - // Use constructor since Builder doesn't have isFinal method - TaskStatusUpdateEvent tsue = new TaskStatusUpdateEvent( - "1234", - completedStatus, - "xyz", - completedStatus.state().isFinal(), // Derive from state - null - ); - io.a2a.grpc.TaskStatusUpdateEvent result = ProtoUtils.ToProto.taskStatusUpdateEvent(tsue); - assertEquals("1234", result.getTaskId()); - assertEquals("xyz", result.getContextId()); - // Note: isFinal field has been removed from the proto (field 4 is reserved) - // It is now derived from status.state().isFinal() - assertEquals(io.a2a.grpc.TaskState.TASK_STATE_COMPLETED, result.getStatus().getState()); - } - - @Test - public void convertSendMessageConfiguration() { - MessageSendConfiguration configuration = MessageSendConfiguration.builder() - .acceptedOutputModes(List.of("text")) - .build(); - SendMessageConfiguration result = ProtoUtils.ToProto.messageSendConfiguration(configuration); - assertFalse(result.getBlocking()); - assertEquals(1, result.getAcceptedOutputModesCount()); - assertEquals("text", result.getAcceptedOutputModesBytes(0).toStringUtf8()); - } - - @Test - public void convertTaskTimestampStatus() { - OffsetDateTime expectedTimestamp = OffsetDateTime.parse("2024-10-05T12:34:56Z"); - TaskStatus testStatus = new TaskStatus(TaskState.TASK_STATE_COMPLETED, null, expectedTimestamp); - Task task = Task.builder() - .id("task-123") - .contextId("context-456") - .status(testStatus) - .build(); - - io.a2a.grpc.Task grpcTask = ProtoUtils.ToProto.task(task); - task = ProtoUtils.FromProto.task(grpcTask); - TaskStatus status = task.status(); - assertEquals(TaskState.TASK_STATE_COMPLETED, status.state()); - assertNotNull(status.timestamp()); - assertEquals(expectedTimestamp, status.timestamp()); - } - - @Test - public void convertDeleteTaskPushNotificationConfigRequest() { - DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams( - "task-123", - "config-456" - ); - - io.a2a.grpc.DeleteTaskPushNotificationConfigRequest result = - ProtoUtils.ToProto.deleteTaskPushNotificationConfigRequest(params); - - assertEquals("task-123", result.getTaskId()); - assertEquals("config-456", result.getId()); - - // Test round-trip conversion - DeleteTaskPushNotificationConfigParams convertedBack = - ProtoUtils.FromProto.deleteTaskPushNotificationConfigParams(result); - assertEquals("task-123", convertedBack.taskId()); - assertEquals("config-456", convertedBack.id()); - } - - @Test - public void convertListTaskPushNotificationConfigRequest() { - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams("task-789"); - - io.a2a.grpc.ListTaskPushNotificationConfigRequest result = - ProtoUtils.ToProto.listTaskPushNotificationConfigRequest(params); - - assertEquals("task-789", result.getTaskId()); - - // Test round-trip conversion - ListTaskPushNotificationConfigParams convertedBack = - ProtoUtils.FromProto.listTaskPushNotificationConfigParams(result); - assertEquals("task-789", convertedBack.id()); - } -} diff --git a/spec/pom.xml b/spec/pom.xml deleted file mode 100644 index 89a06c9ce..000000000 --- a/spec/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - a2a-java-sdk-spec - - jar - - Java SDK A2A Spec - Java SDK for the Agent2Agent Protocol (A2A) - Spec - - - - ${project.groupId} - a2a-java-sdk-common - - - com.google.code.gson - gson - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-params - test - - - - \ No newline at end of file diff --git a/spec/src/main/java/io/a2a/spec/A2AClientError.java b/spec/src/main/java/io/a2a/spec/A2AClientError.java deleted file mode 100644 index 018c468a5..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AClientError.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.a2a.spec; - -/** - * Base exception for A2A client-specific error conditions. - *

    - * This is a specialized exception hierarchy for client-side errors, distinct from - * {@link A2AClientException}. It is used for errors that occur during client SDK - * operations such as validation, state management, and protocol handling. - *

    - * Specialized subclasses: - *

      - *
    • {@link A2AClientHTTPError} - HTTP transport errors with status codes
    • - *
    • {@link A2AClientJSONError} - JSON serialization/deserialization errors
    • - *
    • {@link A2AClientInvalidStateError} - Invalid client state errors
    • - *
    • {@link A2AClientInvalidArgsError} - Invalid argument errors
    • - *
    - * - * @see A2AClientException for general client exceptions - * @see A2AClientHTTPError for HTTP-specific errors - * @see A2AClientJSONError for JSON-specific errors - * @see A2AClientInvalidStateError for invalid state errors - * @see A2AClientInvalidArgsError for invalid argument errors - */ -public class A2AClientError extends RuntimeException { - /** - * Constructs a new A2AClientError with no detail message. - */ - public A2AClientError() { - } - - /** - * Constructs a new A2AClientError with the specified detail message. - * - * @param message the detail message - */ - public A2AClientError(String message) { - super(message); - } - - /** - * Constructs a new A2AClientError with the specified detail message and cause. - * - * @param message the detail message - * @param cause the cause of this exception - */ - public A2AClientError(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AClientException.java b/spec/src/main/java/io/a2a/spec/A2AClientException.java deleted file mode 100644 index 72eeebd47..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AClientException.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.a2a.spec; - -/** - * Exception indicating a client-side failure in A2A Protocol operations. - *

    - * This exception is thrown by A2A client implementations when encountering errors - * during communication with agents, response validation, or client-side processing. - *

    - * Common scenarios: - *

      - *
    • Network communication failures
    • - *
    • Invalid agent responses ({@link A2AClientError})
    • - *
    • HTTP errors ({@link A2AClientHTTPError})
    • - *
    • JSON parsing errors ({@link A2AClientJSONError})
    • - *
    - * - * @see A2AException for the base exception class - * @see A2AServerException for server-side errors - * @see A2AClientError for more specific client errors - */ -public class A2AClientException extends A2AException { - - /** - * Constructs a new A2AClientException with no detail message or cause. - */ - public A2AClientException() { - super(); - } - - /** - * Constructs a new A2AClientException with the specified detail message. - * - * @param msg the detail message - */ - public A2AClientException(final String msg) { - super(msg); - } - - /** - * Constructs a new A2AClientException with the specified cause. - * - * @param cause the cause of this exception - */ - public A2AClientException(final Throwable cause) { - super(cause); - } - - /** - * Constructs a new A2AClientException with the specified detail message and cause. - * - * @param msg the detail message - * @param cause the cause of this exception - */ - public A2AClientException(final String msg, final Throwable cause) { - super(msg, cause); - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java b/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java deleted file mode 100644 index 5e7cd33a1..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; - -/** - * Client exception indicating an HTTP transport error with a specific status code. - *

    - * This exception is thrown when HTTP communication with an A2A agent fails, - * capturing both the HTTP status code and error message. It is used for non-2xx - * HTTP responses that don't contain valid A2A Protocol error responses. - *

    - * Common HTTP status codes: - *

      - *
    • 4xx - Client errors (400 Bad Request, 401 Unauthorized, 404 Not Found, etc.)
    • - *
    • 5xx - Server errors (500 Internal Server Error, 503 Service Unavailable, etc.)
    • - *
    - *

    - * Usage example: - *

    {@code
    - * if (response.statusCode() >= 400) {
    - *     throw new A2AClientHTTPError(
    - *         response.statusCode(),
    - *         "HTTP error: " + response.statusMessage(),
    - *         response.body()
    - *     );
    - * }
    - * }
    - * - * @see A2AClientError for the base client error class - * @see HTTP Status Codes - */ -public class A2AClientHTTPError extends A2AClientError { - /** - * The HTTP status code. - */ - private final int code; - - /** - * The error message. - */ - private final String message; - - /** - * Creates a new HTTP client error with the specified status code and message. - * - * @param code the HTTP status code - * @param message the error message - * @param data additional error data (may be the response body) - * @throws IllegalArgumentException if code or message is null - */ - public A2AClientHTTPError(int code, String message, Object data) { - Assert.checkNotNullParam("code", code); - Assert.checkNotNullParam("message", message); - this.code = code; - this.message = message; - } - - /** - * Gets the error code - * - * @return the error code - */ - public int getCode() { - return code; - } - - /** - * Gets the error message - * - * @return the error message - */ - @Override - public String getMessage() { - return message; - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AClientInvalidArgsError.java b/spec/src/main/java/io/a2a/spec/A2AClientInvalidArgsError.java deleted file mode 100644 index ecf87e395..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AClientInvalidArgsError.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.a2a.spec; - -/** - * Client exception indicating invalid arguments provided to a client operation. - *

    - * This exception is thrown when parameters passed to A2A client SDK methods fail - * validation. This is distinct from {@link InvalidParamsError}, which represents - * server-side parameter validation errors. - *

    - * Common scenarios: - *

      - *
    • Null values for required parameters
    • - *
    • Invalid parameter combinations
    • - *
    • Parameter values outside acceptable ranges
    • - *
    • Malformed URIs or identifiers
    • - *
    - *

    - * Usage example: - *

    {@code
    - * if (agentUrl == null || agentUrl.isEmpty()) {
    - *     throw new A2AClientInvalidArgsError("agentUrl cannot be null or empty");
    - * }
    - * }
    - * - * @see A2AClientError for the base client error class - * @see InvalidParamsError for server-side parameter errors - */ -public class A2AClientInvalidArgsError extends A2AClientError { - - /** - * Creates a new invalid arguments error with no message. - */ - public A2AClientInvalidArgsError() { - } - - /** - * Creates a new invalid arguments error with the specified message. - * - * @param message the error message - */ - public A2AClientInvalidArgsError(String message) { - super("Invalid arguments error: " + message); - } - - /** - * Creates a new invalid arguments error with the specified message and cause. - * - * @param message the error message - * @param cause the underlying cause - */ - public A2AClientInvalidArgsError(String message, Throwable cause) { - super("Invalid arguments error: " + message, cause); - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AClientInvalidStateError.java b/spec/src/main/java/io/a2a/spec/A2AClientInvalidStateError.java deleted file mode 100644 index f710a85b3..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AClientInvalidStateError.java +++ /dev/null @@ -1,53 +0,0 @@ -package io.a2a.spec; - -/** - * Client exception indicating an invalid state for the requested operation. - *

    - * This exception is thrown when a client operation is attempted while the client - * is in a state that doesn't permit that operation. This ensures proper sequencing - * and lifecycle management of client operations. - *

    - * Common scenarios: - *

      - *
    • Attempting to send messages before client initialization
    • - *
    • Trying to cancel a task after the client connection is closed
    • - *
    • Performing operations on a client that has been shut down
    • - *
    • Violating client state machine transitions
    • - *
    - *

    - * Usage example: - *

    {@code
    - * if (!client.isConnected()) {
    - *     throw new A2AClientInvalidStateError("Client not connected");
    - * }
    - * }
    - * - * @see A2AClientError for the base client error class - */ -public class A2AClientInvalidStateError extends A2AClientError { - - /** - * Creates a new invalid state error with no message. - */ - public A2AClientInvalidStateError() { - } - - /** - * Creates a new invalid state error with the specified message. - * - * @param message the error message - */ - public A2AClientInvalidStateError(String message) { - super("Invalid state error: " + message); - } - - /** - * Creates a new invalid state error with the specified message and cause. - * - * @param message the error message - * @param cause the underlying cause - */ - public A2AClientInvalidStateError(String message, Throwable cause) { - super("Invalid state error: " + message, cause); - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java b/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java deleted file mode 100644 index 3cf7fa7ab..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.a2a.spec; - -/** - * Client exception indicating a JSON serialization or deserialization error. - *

    - * This exception is thrown when the A2A client SDK encounters errors while - * parsing JSON responses from agents or serializing requests. This typically - * indicates: - *

      - *
    • Malformed JSON in agent responses
    • - *
    • Unexpected JSON structure or field types
    • - *
    • Missing required JSON fields
    • - *
    • JSON encoding/decoding errors
    • - *
    - *

    - * Usage example: - *

    {@code
    - * try {
    - *     AgentCard card = objectMapper.readValue(json, AgentCard.class);
    - * } catch (io.a2a.json.JsonProcessingException e) {
    - *     throw new A2AClientJSONError("Failed to parse agent card", e);
    - * }
    - * }
    - * - * @see A2AClientError for the base client error class - * @see JSONParseError for protocol-level JSON errors - */ -public class A2AClientJSONError extends A2AClientError { - - /** - * Creates a new JSON error with no message. - */ - public A2AClientJSONError() { - } - - /** - * Creates a new JSON error with the specified message. - * - * @param message the error message - */ - public A2AClientJSONError(String message) { - super(message); - } - - /** - * Creates a new JSON error with the specified message and cause. - * - * @param message the error message - * @param cause the underlying cause - */ - public A2AClientJSONError(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AError.java b/spec/src/main/java/io/a2a/spec/A2AError.java deleted file mode 100644 index c81bbbe32..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AError.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Marker interface for A2A Protocol error events. - *

    - * This interface extends {@link Event} to allow errors to be transmitted as events - * in the A2A Protocol's event stream. All protocol-level errors implement this interface, - * enabling uniform error handling across both streaming and non-streaming communication. - *

    - * A2A errors typically extend {@link A2AError} to provide JSON-RPC 2.0 compliant - * error responses with standard error codes, messages, and optional additional data. - *

    - * Common implementations include: - *

      - *
    • {@link InvalidParamsError} - Invalid method parameters
    • - *
    • {@link InvalidRequestError} - Malformed request
    • - *
    • {@link MethodNotFoundError} - Unknown method
    • - *
    • {@link InternalError} - Server-side error
    • - *
    • {@link TaskNotFoundError} - Task does not exist
    • - *
    • And others for specific protocol error conditions
    • - *
    - * - * @see Event for the base event interface - * @see A2AError for the base error implementation - * @see JSON-RPC 2.0 Error Object - * @see A2A Protocol Specification - */ -public class A2AError extends RuntimeException implements Event { - /** - * The numeric error code (see JSON-RPC 2.0 spec for standard codes). - */ - private final Integer code; - - /** - * Additional error information (structure defined by the error code). - */ - private final @Nullable Object data; - - /** - * Constructs a JSON-RPC error with the specified code, message, and optional data. - *

    - * This constructor is used by Jackson for JSON deserialization. - * - * @param code the numeric error code (required, see JSON-RPC 2.0 spec for standard codes) - * @param message the human-readable error message (required) - * @param data additional error information, structure defined by the error code (optional) - * @throws IllegalArgumentException if code or message is null - */ - public A2AError(Integer code, String message, @Nullable Object data) { - super(Assert.checkNotNullParam("message", message)); - this.code = Assert.checkNotNullParam("code", code); - this.data = data; - } - - /** - * Gets the numeric error code indicating the error type. - *

    - * Standard JSON-RPC 2.0 error codes: - *

      - *
    • -32700: Parse error
    • - *
    • -32600: Invalid Request
    • - *
    • -32601: Method not found
    • - *
    • -32602: Invalid params
    • - *
    • -32603: Internal error
    • - *
    • -32000 to -32099: Server error (implementation-defined)
    • - *
    - * - * @return the error code - */ - public Integer getCode() { - return code; - } - - /** - * Gets additional information about the error. - *

    - * The structure and type of the data field is defined by the specific error code. - * It may contain detailed debugging information, validation errors, or other - * context-specific data to help diagnose the error. - * - * @return the error data, or null if not provided - */ - public @Nullable Object getData() { - return data; - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java b/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java deleted file mode 100644 index 8eb4c6584..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AErrorCodes.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.a2a.spec; - -/** - * All the error codes for A2A errors. - */ -public interface A2AErrorCodes { - - /** Error code indicating the requested task was not found (-32001). */ - int TASK_NOT_FOUND_ERROR_CODE = -32001; - - /** Error code indicating the task cannot be canceled in its current state (-32002). */ - int TASK_NOT_CANCELABLE_ERROR_CODE = -32002; - - /** Error code indicating push notifications are not supported by this agent (-32003). */ - int PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE = -32003; - - /** Error code indicating the requested operation is not supported (-32004). */ - int UNSUPPORTED_OPERATION_ERROR_CODE = -32004; - - /** Error code indicating the content type is not supported (-32005). */ - int CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE = -32005; - - /** Error code indicating the agent returned an invalid response (-32006). */ - int INVALID_AGENT_RESPONSE_ERROR_CODE = -32006; - - /** Error code indicating extended agent card is not configured (-32007). */ - int EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE = -32007; - - /** Error code indicating client requested use of an extension marked as required: true in the Agent Card - * but the client did not declare support for it in the request (-32008). */ - int EXTENSION_SUPPORT_REQUIRED_ERROR = -32008; - - /** Error code indicating the A2A protocol version specified in the request (via A2A-Version service parameter) - * is not supported by the agent (-32009). */ - int VERSION_NOT_SUPPORTED_ERROR_CODE = -32009; - - /** JSON-RPC error code for invalid request structure (-32600). */ - int INVALID_REQUEST_ERROR_CODE = -32600; - - /** JSON-RPC error code for method not found (-32601). */ - int METHOD_NOT_FOUND_ERROR_CODE = -32601; - - /** JSON-RPC error code for invalid method parameters (-32602). */ - int INVALID_PARAMS_ERROR_CODE = -32602; - - /** JSON-RPC error code for internal server errors (-32603). */ - int INTERNAL_ERROR_CODE = -32603; - - /** JSON-RPC error code for JSON parsing errors (-32700). */ - int JSON_PARSE_ERROR_CODE = -32700; -} diff --git a/spec/src/main/java/io/a2a/spec/A2AException.java b/spec/src/main/java/io/a2a/spec/A2AException.java deleted file mode 100644 index e48b5fc81..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AException.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.a2a.spec; - -/** - * Base exception for A2A Protocol-related failures. - *

    - * This is the root exception class for all A2A Protocol exceptions, providing a common - * base type for exception handling. It extends {@link RuntimeException} to allow unchecked - * exception propagation throughout A2A client and server implementations. - *

    - * Specialized subclasses: - *

      - *
    • {@link A2AServerException} - Server-side failures
    • - *
    • {@link A2AClientException} - Client-side failures
    • - *
    - * - * @see A2AServerException for server-side errors - * @see A2AClientException for client-side errors - * @see A2A Protocol Specification - */ -public class A2AException extends RuntimeException { - - /** - * Constructs a new {@code A2AException} instance. The message is left blank ({@code null}), and no - * cause is specified. - */ - public A2AException() { - } - - /** - * Constructs a new {@code A2AException} instance with an initial message. No cause is specified. - * - * @param msg the message - */ - public A2AException(final String msg) { - super(msg); - } - - /** - * Constructs a new {@code A2AException} instance with an initial cause. If a non-{@code null} cause - * is specified, its message is used to initialize the message of this {@code A2AException}; otherwise - * the message is left blank ({@code null}). - * - * @param cause the cause - */ - public A2AException(final Throwable cause) { - super(cause); - } - - /** - * Constructs a new {@code A2AException} instance with an initial message and cause. - * - * @param msg the message - * @param cause the cause - */ - public A2AException(final String msg, final Throwable cause) { - super(msg, cause); - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AMethods.java b/spec/src/main/java/io/a2a/spec/A2AMethods.java deleted file mode 100644 index 1731077fe..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AMethods.java +++ /dev/null @@ -1,32 +0,0 @@ - -package io.a2a.spec; - -/** - * Constants defining the A2A protocol method names. - */ -public interface A2AMethods { - /** Method name for canceling a task. */ - String CANCEL_TASK_METHOD = "CancelTask"; - /** Method name for deleting task push notification configuration. */ - String DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "DeleteTaskPushNotificationConfig"; - /** Method name for getting extended agent card information. */ - String GET_EXTENDED_AGENT_CARD_METHOD = "GetExtendedAgentCard"; - /** Method name for getting a task. */ - String GET_TASK_METHOD = "GetTask"; - /** Method name for getting task push notification configuration. */ - String GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "GetTaskPushNotificationConfig"; - /** Method name for listing tasks. */ - String LIST_TASK_METHOD = "ListTasks"; - /** Method name for listing task push notification configurations. */ - String LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "ListTaskPushNotificationConfig"; - /** Method name for sending a message. */ - String SEND_MESSAGE_METHOD = "SendMessage"; - /** Method name for sending a streaming message. */ - String SEND_STREAMING_MESSAGE_METHOD = "SendStreamingMessage"; - /** Method name for setting task push notification configuration. */ - String SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "CreateTaskPushNotificationConfig"; - /** Method name for subscribing to task events. */ - String SUBSCRIBE_TO_TASK_METHOD = "SubscribeToTask"; - - -} diff --git a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java b/spec/src/main/java/io/a2a/spec/A2AProtocolError.java deleted file mode 100644 index b03ba4080..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AProtocolError.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.a2a.spec; - -import org.jspecify.annotations.Nullable; - -/** - * Represents a protocol-level error in the A2A Protocol with a reference URL. - *

    - * This error extends {@link A2AError} to include a URL field that provides a reference - * to documentation, specification details, or additional context about the protocol error. - * This is particularly useful for protocol version mismatches, unsupported features, or - * other situations where pointing to the protocol specification would help diagnose the issue. - * - * @see A2AError for the base error implementation - */ -public class A2AProtocolError extends A2AError { - - /** - * URL reference for additional information about this protocol error. - */ - private final @Nullable String url; - - /** - * Constructs a protocol error with the specified code, message, data, and reference URL. - * - * @param code the numeric error code (required, see JSON-RPC 2.0 spec for standard codes) - * @param message the human-readable error message (required) - * @param data additional error information, structure defined by the error code (optional) - * @param url URL reference providing additional context about this protocol error (optional) - */ - public A2AProtocolError(Integer code, String message, @Nullable Object data, @Nullable String url) { - super(code, message, data); - this.url = url; - } - - /** - * Gets the URL reference for additional information about this protocol error. - *

    - * This URL typically points to protocol specification documentation or other resources - * that provide context about the error condition. - * - * @return the reference URL, or null if not provided - */ - public @Nullable String getUrl() { - return url; - } -} diff --git a/spec/src/main/java/io/a2a/spec/A2AServerException.java b/spec/src/main/java/io/a2a/spec/A2AServerException.java deleted file mode 100644 index e2d2cf85c..000000000 --- a/spec/src/main/java/io/a2a/spec/A2AServerException.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.a2a.spec; - -/** - * Exception indicating a server-side failure in A2A Protocol operations. - *

    - * This exception is thrown by A2A server implementations when encountering errors - * during request processing, task execution, or other server-side operations. - *

    - * Common scenarios: - *

      - *
    • Agent execution failures
    • - *
    • Task store persistence errors
    • - *
    • Resource exhaustion or limits exceeded
    • - *
    • Configuration errors
    • - *
    - * - * @see A2AException for the base exception class - * @see A2AClientException for client-side errors - */ -public class A2AServerException extends A2AException { - - /** - * Creates a new A2AServerException with no message. - */ - public A2AServerException() { - super(); - } - - /** - * Creates a new A2AServerException with the specified message. - * - * @param msg the exception message - */ - public A2AServerException(final String msg) { - super(msg); - } - - /** - * Creates a new A2AServerException with the specified cause. - * - * @param cause the underlying cause - */ - public A2AServerException(final Throwable cause) { - super(cause); - } - - /** - * Creates a new A2AServerException with the specified message and cause. - * - * @param msg the exception message - * @param cause the underlying cause - */ - public A2AServerException(final String msg, final Throwable cause) { - super(msg, cause); - } -} diff --git a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java b/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java deleted file mode 100644 index 676d43835..000000000 --- a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java +++ /dev/null @@ -1,180 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * API key security scheme for agent authentication. - *

    - * This security scheme uses an API key that can be sent in a header, query parameter, - * or cookie to authenticate requests to the agent. - *

    - * Corresponds to the OpenAPI "apiKey" security scheme type. - * - * @param location the location where the API key is sent (required) - * @param name the name of the API key parameter (required) - * @param description a human-readable description (optional) - * @see SecurityScheme for the base interface - * @see OpenAPI Security Scheme - * @see A2A Protocol Specification - */ -public record APIKeySecurityScheme(Location location, String name, @Nullable - String description) implements SecurityScheme { - - /** - * The security scheme type identifier for API key authentication. - */ - public static final String TYPE = "apiKeySecurityScheme"; - - @Override - public String type() { - return TYPE; - } - - /** - * Compact constructor with validation. - * - * @param location the location where the API key is sent (required) - * @param name the name of the API key parameter (required) - * @param description a human-readable description (optional) - * @throws IllegalArgumentException if location or name is null - */ - public APIKeySecurityScheme { - Assert.checkNotNullParam("location", location); - Assert.checkNotNullParam("name", name); - } - - /** - * Represents the location of the API key. - */ - public enum Location { - /** - * API key sent in a cookie. - */ - COOKIE("cookie"), - /** - * API key sent in an HTTP header. - */ - HEADER("header"), - /** - * API key sent as a query parameter. - */ - QUERY("query"); - - private final String location; - - Location(String location) { - this.location = location; - } - - /** - * Converts this location to its string representation. - * - * @return the string representation of this location - */ - public String asString() { - return location; - } - - /** - * Converts a string to a Location enum value. - * - * @param location the string location ("cookie", "header", or "query") - * @return the corresponding Location enum value - * @throws IllegalArgumentException if the location string is invalid - */ - public static Location fromString(String location) { - switch (location) { - case "cookie" -> { - return COOKIE; - } - case "header" -> { - return HEADER; - } - case "query" -> { - return QUERY; - } - default -> - throw new IllegalArgumentException("Invalid API key location: " + location); - } - } - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing immutable {@link APIKeySecurityScheme} instances. - *

    - * Example usage: - *

    {@code
    -     * APIKeySecurityScheme scheme = APIKeySecurityScheme.builder()
    -     *     .location(Location.HEADER)
    -     *     .name("X-API-Key")
    -     *     .description("API key authentication")
    -     *     .build();
    -     * }
    - */ - public static class Builder { - - private @Nullable Location location; - private @Nullable String name; - private @Nullable String description; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the location where the API key should be sent. - * - * @param location the API key location (header, query, or cookie) (required) - * @return this builder for method chaining - */ - public Builder location(Location location) { - this.location = location; - return this; - } - - /** - * Sets the name of the API key parameter. - * - * @param name the parameter name (required) - * @return this builder for method chaining - */ - public Builder name(String name) { - this.name = name; - return this; - } - - /** - * Sets the human-readable description of the security scheme. - * - * @param description the description (optional) - * @return this builder for method chaining - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * Builds a new immutable {@link APIKeySecurityScheme} from the current builder state. - * - * @return a new APIKeySecurityScheme instance - * @throws IllegalArgumentException if location or name is null - */ - public APIKeySecurityScheme build() { - return new APIKeySecurityScheme(Assert.checkNotNullParam("location", location), - Assert.checkNotNullParam("name", name), description); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java deleted file mode 100644 index e36088a42..000000000 --- a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java +++ /dev/null @@ -1,137 +0,0 @@ -package io.a2a.spec; - -import java.util.List; -import org.jspecify.annotations.Nullable; - -/** - * Defines optional capabilities supported by an agent in the A2A Protocol. - *

    - * AgentCapabilities advertises which advanced features an agent supports beyond the - * basic request-response pattern. Clients can inspect these capabilities to determine - * how to interact with the agent and what features are available. - *

    - * Core Capabilities: - *

      - *
    • streaming: Agent can produce incremental results via streaming responses, - * allowing clients to receive partial artifacts as they are generated rather than - * waiting for task completion
    • - *
    • pushNotifications: Agent can send proactive notifications to clients - * when task state changes, eliminating the need for polling
    • - *
    - *

    - * Capabilities are declared in the {@link AgentCard} and are immutable for the lifetime - * of the agent instance. This class uses the Builder pattern for construction. - * - * @param streaming whether the agent supports streaming responses with incremental artifacts - * @param pushNotifications whether the agent supports push notifications for state changes - * @param extendedAgentCard whether the agent supports an extended agent card - * @param extensions list of custom extensions supported by the agent (optional) - * @see AgentCard - * @see AgentExtension - * @see A2A Protocol Specification - */ -public record AgentCapabilities(boolean streaming, - boolean pushNotifications, - boolean extendedAgentCard, - @Nullable List extensions) { - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - /** - * Builder for constructing immutable {@link AgentCapabilities} instances. - *

    - * The Builder pattern provides a fluent API for setting capability flags. - * All capabilities default to false if not explicitly set. - *

    - * Example usage: - *

    {@code
    -     * AgentCapabilities capabilities = AgentCapabilities.builder()
    -     *     .streaming(true)
    -     *     .pushNotifications(false)
    -     *     .build();
    -     * }
    - */ - public static class Builder { - - private boolean streaming; - private boolean pushNotifications; - private boolean extendedAgentCard; - private @Nullable List extensions; - - /** - * Creates a new Builder with all capabilities set to false by default. - */ - private Builder() { - } - - /** - * Sets whether the agent supports streaming responses. - *

    - * When enabled, clients can subscribe to task updates and receive - * incremental artifacts as the agent produces them. - * - * @param streaming true if streaming is supported, false otherwise - * @return this builder for method chaining - */ - public Builder streaming(boolean streaming) { - this.streaming = streaming; - return this; - } - - /** - * Sets whether the agent supports push notifications. - *

    - * When enabled, the agent can proactively notify clients of task - * state changes, eliminating the need for polling. - * - * @param pushNotifications true if push notifications are supported, false otherwise - * @return this builder for method chaining - */ - public Builder pushNotifications(boolean pushNotifications) { - this.pushNotifications = pushNotifications; - return this; - } - - /** - * Sets whether the agent supports an extended agent card. - * state transition history. - * - * @param extendedAgentCard true if an extended agent card is supported, false otherwise - * @return this builder for method chaining - */ - public Builder extendedAgentCard(boolean extendedAgentCard) { - this.extendedAgentCard = extendedAgentCard; - return this; - } - - /** - * Sets the list of custom extensions supported by the agent. - *

    - * Extensions allow agents to advertise proprietary or experimental - * capabilities beyond the core A2A Protocol. - * - * @param extensions list of agent extensions (optional) - * @return this builder for method chaining - * @see AgentExtension - */ - public Builder extensions(List extensions) { - this.extensions = extensions; - return this; - } - - /** - * Builds an immutable {@link AgentCapabilities} from the current builder state. - * - * @return a new AgentCapabilities instance - */ - public AgentCapabilities build() { - return new AgentCapabilities(streaming, pushNotifications, extendedAgentCard, extensions); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/AgentCard.java b/spec/src/main/java/io/a2a/spec/AgentCard.java deleted file mode 100644 index 4bfca0284..000000000 --- a/spec/src/main/java/io/a2a/spec/AgentCard.java +++ /dev/null @@ -1,405 +0,0 @@ -package io.a2a.spec; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * The AgentCard is a self-describing manifest for an agent in the A2A Protocol. - *

    - * An AgentCard provides essential metadata about an agent, including its identity, capabilities, - * supported skills, communication methods, and security requirements. It serves as the primary - * discovery mechanism for clients to understand what an agent can do and how to interact with it. - *

    - * The AgentCard corresponds to the {@code AgentCard} type in the A2A Protocol specification, - * defining the contract between clients and agents for capability advertisement. - *

    - * This class is immutable and uses the Builder pattern for construction to handle the mix of - * required and optional fields defined by the specification. - *

    - * Important: The {@link #supportedInterfaces()} field specifies how clients can - * communicate with the agent. Each entry combines a protocol binding (e.g., "JSONRPC", - * "GRPC") with a URL endpoint. The first entry in the list is the preferred interface. - * - * @param name the human-readable name of the agent (required) - * @param description a brief description of the agent's purpose and functionality (required) - * @param provider information about the organization or entity providing the agent (optional) - * @param version the version of the agent implementation (required) - * @param documentationUrl URL to human-readable documentation for the agent (optional) - * @param capabilities the capabilities supported by this agent (required) - * @param defaultInputModes list of supported input modes, e.g., "text", "audio" (required) - * @param defaultOutputModes list of supported output modes, e.g., "text", "audio" (required) - * @param skills list of skills that this agent can perform (required) - * @param securitySchemes map of security scheme names to their definitions (optional) - * @param securityRequirements list of security requirements for accessing the agent (optional) - * @param iconUrl URL to an icon representing the agent (optional) - * @param supportedInterfaces ordered list of protocol+URL interface combinations; first entry is preferred (required) - * @param signatures digital signatures verifying the authenticity of the agent card (optional) - * @see AgentInterface - * @see A2A Protocol Specification - */ -public record AgentCard( - String name, - String description, - @Nullable AgentProvider provider, - String version, - @Nullable String documentationUrl, - AgentCapabilities capabilities, - List defaultInputModes, - List defaultOutputModes, - List skills, - @Nullable Map securitySchemes, - @Nullable List securityRequirements, - @Nullable String iconUrl, - List supportedInterfaces, - @Nullable List signatures) { - - /** - * Compact constructor that validates required fields. - * - * @param name the name parameter (see class-level JavaDoc) - * @param description the description parameter (see class-level JavaDoc) - * @param provider the provider parameter (see class-level JavaDoc) - * @param version the version parameter (see class-level JavaDoc) - * @param documentationUrl the documentationUrl parameter (see class-level JavaDoc) - * @param capabilities the capabilities parameter (see class-level JavaDoc) - * @param defaultInputModes the defaultInputModes parameter (see class-level JavaDoc) - * @param defaultOutputModes the defaultOutputModes parameter (see class-level JavaDoc) - * @param skills the skills parameter (see class-level JavaDoc) - * @param securitySchemes the securitySchemes parameter (see class-level JavaDoc) - * @param securityRequirements the security parameter (see class-level JavaDoc) - * @param iconUrl the iconUrl parameter (see class-level JavaDoc) - * @param supportedInterfaces the supportedInterfaces parameter (see class-level JavaDoc) - * @param signatures the signatures parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if any required field is null - */ - public AgentCard { - Assert.checkNotNullParam("capabilities", capabilities); - Assert.checkNotNullParam("defaultInputModes", defaultInputModes); - Assert.checkNotNullParam("defaultOutputModes", defaultOutputModes); - Assert.checkNotNullParam("description", description); - Assert.checkNotNullParam("name", name); - Assert.checkNotNullParam("skills", skills); - Assert.checkNotNullParam("supportedInterfaces", supportedInterfaces); - Assert.checkNotNullParam("version", version); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Create a new Builder initialized with values from an existing AgentCard. - *

    - * This builder creates defensive copies of mutable collections to ensure - * that modifications to the builder do not affect the original AgentCard. - * - * @param card the AgentCard to copy values from - * @return the builder - */ - public static Builder builder(AgentCard card) { - return new Builder(card); - } - - /** - * Builder for constructing immutable {@link AgentCard} instances. - *

    - * The Builder pattern is used to enforce immutability of AgentCard objects while providing - * a fluent API for setting required and optional fields. This approach ensures that once - * an AgentCard is created, its state cannot be modified, which is important for thread-safety - * and protocol correctness. - *

    - * Example usage: - *

    {@code
    -     * AgentCard card = AgentCard.builder()
    -     *     .name("Weather Agent")
    -     *     .description("Provides weather information")
    -     *     .supportedInterfaces(List.of(
    -     *         new AgentInterface("JSONRPC", "http://localhost:9999")))
    -     *     .version("1.0.0")
    -     *     .capabilities(new AgentCapabilities.Builder()
    -     *         .streaming(true)
    -     *         .build())
    -     *     .defaultInputModes(List.of("text"))
    -     *     .defaultOutputModes(List.of("text"))
    -     *     .skills(List.of(
    -     *         new AgentSkill.Builder()
    -     *             .id("weather_query")
    -     *             .name("Weather Queries")
    -     *             .build()
    -     *     ))
    -     *     .build();
    -     * }
    - */ - public static class Builder { - - private @Nullable String name; - private @Nullable String description; - private @Nullable AgentProvider provider; - private @Nullable String version; - private @Nullable String documentationUrl; - private @Nullable AgentCapabilities capabilities; - private @Nullable List defaultInputModes; - private @Nullable List defaultOutputModes; - private @Nullable List skills; - private @Nullable Map securitySchemes; - private @Nullable List securityRequirements; - private @Nullable String iconUrl; - private @Nullable List supportedInterfaces; - private @Nullable List signatures; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Creates a new Builder initialized with values from an existing AgentCard. - *

    - * This constructor creates defensive copies of mutable collections to ensure - * that modifications to the builder do not affect the original AgentCard. - * - * @param card the AgentCard to copy values from - */ - private Builder(AgentCard card) { - this.name = card.name; - this.description = card.description; - this.provider = card.provider; - this.version = card.version; - this.documentationUrl = card.documentationUrl; - this.capabilities = card.capabilities; - this.defaultInputModes = card.defaultInputModes != null ? new ArrayList<>(card.defaultInputModes) : Collections.emptyList(); - this.defaultOutputModes = card.defaultOutputModes != null ? new ArrayList<>(card.defaultOutputModes) : Collections.emptyList(); - this.skills = card.skills != null ? new ArrayList<>(card.skills) : Collections.emptyList(); - this.securitySchemes = card.securitySchemes != null ? Map.copyOf(card.securitySchemes) : Collections.emptyMap(); - this.securityRequirements = card.securityRequirements != null ? new ArrayList<>(card.securityRequirements) : Collections.emptyList(); - this.iconUrl = card.iconUrl; - this.supportedInterfaces = card.supportedInterfaces != null ? new ArrayList<>(card.supportedInterfaces) : Collections.emptyList(); - this.signatures = card.signatures != null ? new ArrayList<>(card.signatures) : null; - } - - /** - * Sets the human-readable name of the agent. - * - * @param name the agent name (required) - * @return this builder for method chaining - */ - public Builder name(String name) { - this.name = name; - return this; - } - - /** - * Sets a brief description of the agent's purpose and functionality. - * - * @param description the agent description (required) - * @return this builder for method chaining - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * Sets information about the organization or entity providing the agent. - * - * @param provider the agent provider (optional) - * @return this builder for method chaining - */ - public Builder provider(AgentProvider provider) { - this.provider = provider; - return this; - } - - /** - * Sets the version of the agent implementation. - * - * @param version the agent version (required) - * @return this builder for method chaining - */ - public Builder version(String version) { - this.version = version; - return this; - } - - /** - * Sets the URL to human-readable documentation for the agent. - * - * @param documentationUrl the documentation URL (optional) - * @return this builder for method chaining - */ - public Builder documentationUrl(String documentationUrl) { - this.documentationUrl = documentationUrl; - return this; - } - - /** - * Sets the capabilities supported by this agent. - *

    - * Capabilities define optional features such as streaming responses, - * push notifications, and state transition history. - * - * @param capabilities the agent capabilities (required) - * @return this builder for method chaining - * @see AgentCapabilities - */ - public Builder capabilities(AgentCapabilities capabilities) { - this.capabilities = capabilities; - return this; - } - - /** - * Sets the list of supported input modes. - *

    - * Input modes define the formats the agent can accept, such as "text", "audio", or "image". - * - * @param defaultInputModes the list of input modes (required, must not be empty) - * @return this builder for method chaining - */ - public Builder defaultInputModes(List defaultInputModes) { - this.defaultInputModes = defaultInputModes; - return this; - } - - /** - * Sets the list of supported output modes. - *

    - * Output modes define the formats the agent can produce, such as "text", "audio", or "image". - * - * @param defaultOutputModes the list of output modes (required, must not be empty) - * @return this builder for method chaining - */ - public Builder defaultOutputModes(List defaultOutputModes) { - this.defaultOutputModes = defaultOutputModes; - return this; - } - - /** - * Sets the list of skills that this agent can perform. - *

    - * Skills represent distinct capabilities or operations the agent can execute, - * such as "weather_query" or "language_translation". - * - * @param skills the list of agent skills (required, must not be empty) - * @return this builder for method chaining - * @see AgentSkill - */ - public Builder skills(List skills) { - this.skills = skills; - return this; - } - - /** - * Sets the map of security scheme definitions. - *

    - * Security schemes define authentication and authorization methods supported - * by the agent, such as OAuth2, API keys, or HTTP authentication. - * - * @param securitySchemes map of scheme names to definitions (optional) - * @return this builder for method chaining - * @see SecurityScheme - */ - public Builder securitySchemes(Map securitySchemes) { - this.securitySchemes = securitySchemes; - return this; - } - - /** - * Sets the list of security requirements for accessing the agent. - * - * @param securityRequirements the list of security requirements (optional) - * @return this builder for method chaining - * @see SecurityRequirement - */ - public Builder securityRequirements(List securityRequirements) { - this.securityRequirements = securityRequirements; - return this; - } - - /** - * Sets the URL to an icon representing the agent. - * - * @param iconUrl the icon URL (optional) - * @return this builder for method chaining - */ - public Builder iconUrl(String iconUrl) { - this.iconUrl = iconUrl; - return this; - } - - /** - * Sets the ordered list of supported protocol interfaces (first entry is preferred). - *

    - * Each interface defines a combination of protocol binding (e.g., "JSONRPC", "GRPC", "REST") - * and URL endpoint for accessing the agent. This is the primary field for declaring how - * clients can communicate with the agent as of protocol version 1.0.0. - *

    - * Example: - *

    {@code
    -         * .supportedInterfaces(List.of(
    -         *     new AgentInterface("JSONRPC", "http://localhost:9999"),
    -         *     new AgentInterface("GRPC", "grpc://localhost:9090")
    -         * ))
    -         * }
    - * - * @param supportedInterfaces the ordered list of supported interfaces (required) - * @return this builder for method chaining - * @see AgentInterface - */ - public Builder supportedInterfaces(List supportedInterfaces) { - this.supportedInterfaces = supportedInterfaces; - return this; - } - - /** - * Sets the digital signatures verifying the authenticity of the agent card. - *

    - * Signatures provide cryptographic proof that the agent card was issued by - * a trusted authority and has not been tampered with. - * - * @param signatures the list of signatures (optional) - * @return this builder for method chaining - * @see AgentCardSignature - */ - public Builder signatures(List signatures) { - this.signatures = signatures; - return this; - } - - /** - * Builds an immutable {@link AgentCard} from the current builder state. - *

    - * This method applies default values for optional fields. - * - * @return a new AgentCard instance - * @throws IllegalArgumentException if any required field is null - */ - public AgentCard build() { - return new AgentCard( - Assert.checkNotNullParam("name", name), - Assert.checkNotNullParam("description", description), - provider, - Assert.checkNotNullParam("version", version), - documentationUrl, - Assert.checkNotNullParam("capabilities", capabilities), - Assert.checkNotNullParam("defaultInputModes", defaultInputModes), - Assert.checkNotNullParam("defaultOutputModes", defaultOutputModes), - Assert.checkNotNullParam("skills", skills), - securitySchemes, - securityRequirements, - iconUrl, - Assert.checkNotNullParam("supportedInterfaces", supportedInterfaces), - signatures); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java b/spec/src/main/java/io/a2a/spec/AgentCardSignature.java deleted file mode 100644 index f87a9b25a..000000000 --- a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java +++ /dev/null @@ -1,132 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import com.google.gson.annotations.SerializedName; -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Represents a digital signature for an {@link AgentCard} using JSON Web Signature (JWS) format. - *

    - * AgentCardSignature provides cryptographic proof that an AgentCard was issued by a trusted - * authority and has not been tampered with. This enables verification of agent authenticity - * and integrity in security-sensitive scenarios. - *

    - * The signature follows RFC 7515 JSON Web Signature (JWS) specification, consisting of: - *

      - *
    • A protected header (Base64URL-encoded JSON) containing algorithm and key information
    • - *
    • An optional unprotected header with additional metadata
    • - *
    • The signature value itself
    • - *
    - *

    - * Multiple signatures can be included in an AgentCard to support different verification - * authorities or key algorithms. - *

    - * This class is immutable. Use the {@link Builder} for construction. - * - * @param header optional unprotected header with additional metadata (optional) - * @param protectedHeader Base64URL-encoded protected header containing algorithm and key info (required) - * @param signature the Base64URL-encoded signature value (required) - * @see AgentCard - * @see RFC 7515 - JSON Web Signature - * @see A2A Protocol Specification - */ -public record AgentCardSignature(@Nullable Map header, @SerializedName("protected")String protectedHeader, - String signature) { - - /** - * Compact constructor that validates required fields. - * - * @param header the header parameter (see class-level JavaDoc) - * @param protectedHeader the protectedHeader parameter (see class-level JavaDoc) - * @param signature the signature parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if protectedHeader or signature is null - */ - public AgentCardSignature { - Assert.checkNotNullParam("protectedHeader", protectedHeader); - Assert.checkNotNullParam("signature", signature); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing immutable {@link AgentCardSignature} instances. - *

    - * Example usage: - *

    {@code
    -     * AgentCardSignature sig = AgentCardSignature.builder()
    -     *     .protectedHeader("eyJhbGciOiJFUzI1NiJ9")
    -     *     .signature("DtEhU3ljbEg8L38VWAfUAqOyKAM6...")
    -     *     .header(Map.of("kid", "2024-01"))
    -     *     .build();
    -     * }
    - */ - public static class Builder { - private @Nullable Map header; - @Nullable String protectedHeader; - @Nullable String signature; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the optional unprotected header with additional metadata. - * - * @param header map of header parameters (optional) - * @return this builder for method chaining - */ - public Builder header(Map header) { - this.header = header; - return this; - } - - /** - * Sets the Base64URL-encoded protected header. - *

    - * The protected header typically contains the algorithm ("alg") and may include - * key identification ("kid") or other parameters that need integrity protection. - * - * @param protectedHeader the Base64URL-encoded protected header (required) - * @return this builder for method chaining - */ - public Builder protectedHeader(String protectedHeader) { - this.protectedHeader = protectedHeader; - return this; - } - - /** - * Sets the Base64URL-encoded signature value. - * - * @param signature the Base64URL-encoded signature (required) - * @return this builder for method chaining - */ - public Builder signature(String signature) { - this.signature = signature; - return this; - } - - /** - * Builds a new immutable {@link AgentCardSignature} from the current builder state. - * - * @return a new AgentCardSignature instance - * @throws IllegalArgumentException if protectedHeader or signature is null - */ - public AgentCardSignature build() { - return new AgentCardSignature( - header, - Assert.checkNotNullParam("protectedHeader", protectedHeader), - Assert.checkNotNullParam("signature", signature)); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/AgentExtension.java b/spec/src/main/java/io/a2a/spec/AgentExtension.java deleted file mode 100644 index de454efad..000000000 --- a/spec/src/main/java/io/a2a/spec/AgentExtension.java +++ /dev/null @@ -1,131 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Represents a protocol extension supported by an agent. - *

    - * AgentExtension declares optional or required capabilities beyond the core A2A Protocol - * specification. Extensions allow agents to advertise support for additional features, - * behaviors, or custom protocol enhancements identified by a unique URI. - *

    - * Extensions may include parameters for configuration and can be marked as required, - * indicating that clients must support the extension to interact with the agent successfully. - *

    - * This class is immutable. Use the {@link Builder} for construction. - * - * @param description a human-readable description of the extension's purpose (optional) - * @param params configuration parameters for the extension (optional) - * @param required whether support for this extension is mandatory for clients (defaults to false) - * @param uri the unique identifier URI for this extension (required) - * @see AgentCard - * @see A2A Protocol Specification - */ -public record AgentExtension (@Nullable String description, @Nullable Map params, boolean required, String uri) { - - /** - * Compact constructor that validates required fields. - * - * @param description the description parameter (see class-level JavaDoc) - * @param params the params parameter (see class-level JavaDoc) - * @param required the required parameter (see class-level JavaDoc) - * @param uri the uri parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if uri is null - */ - public AgentExtension { - Assert.checkNotNullParam("uri", uri); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing immutable {@link AgentExtension} instances. - *

    - * Example usage: - *

    {@code
    -     * AgentExtension ext = AgentExtension.builder()
    -     *     .uri("https://example.com/extensions/custom-auth")
    -     *     .description("Custom authentication extension")
    -     *     .required(true)
    -     *     .params(Map.of("authType", "bearer"))
    -     *     .build();
    -     * }
    - */ - public static class Builder { - @Nullable String description; - @Nullable Map params; - boolean required; - @Nullable String uri; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets a human-readable description of the extension's purpose. - * - * @param description the extension description (optional) - * @return this builder for method chaining - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * Sets configuration parameters for the extension. - * - * @param params map of parameter key-value pairs (optional) - * @return this builder for method chaining - */ - public Builder params(Map params) { - this.params = params; - return this; - } - - /** - * Sets whether support for this extension is mandatory. - * - * @param required true if clients must support this extension (defaults to false) - * @return this builder for method chaining - */ - public Builder required(boolean required) { - this.required = required; - return this; - } - - /** - * Sets the unique identifier URI for this extension. - * - * @param uri the extension URI (required) - * @return this builder for method chaining - */ - public Builder uri(String uri) { - this.uri = uri; - return this; - } - - /** - * Builds a new immutable {@link AgentExtension} from the current builder state. - * - * @return a new AgentExtension instance - * @throws IllegalArgumentException if uri is null - */ - public AgentExtension build() { - return new AgentExtension(description, params, required, Assert.checkNotNullParam("uri", uri)); - } - } - -} diff --git a/spec/src/main/java/io/a2a/spec/AgentInterface.java b/spec/src/main/java/io/a2a/spec/AgentInterface.java deleted file mode 100644 index dccf4cc75..000000000 --- a/spec/src/main/java/io/a2a/spec/AgentInterface.java +++ /dev/null @@ -1,72 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; - -/** - * Declares a combination of a target URL and protocol binding for accessing an agent. - *

    - * AgentInterface defines how clients can connect to and communicate with an agent using - * a specific protocol binding at a particular endpoint. The protocol binding is an open-form - * string that can be extended for other protocol bindings. Core officially supported bindings - * are JSONRPC, GRPC, and HTTP+JSON. - *

    - * Agents may support multiple interfaces to allow flexibility in how clients communicate. - * The {@link AgentCard#supportedInterfaces()} field contains an ordered list of interfaces, - * with the first entry being the preferred method for accessing the agent. - *

    - * This class is immutable. - * - * @param protocolBinding the protocol binding supported at this URL (e.g., "JSONRPC", "GRPC", "HTTP+JSON") (required) - * @param url the endpoint URL where this interface is available; must be a valid absolute HTTPS URL in production - * (required) - * @param tenant the tenant to be set in the request when calling the agent. - * @param protocolVersion the version of the A2A protocol this interface exposes (e.g., "1.0", "0.3") (required) - * @see AgentCard - * @see TransportProtocol - * @see A2A Protocol Specification - */ -public record AgentInterface(String protocolBinding, String url, String tenant, String protocolVersion) { - - /** The default A2A Protocol version used when not explicitly specified. */ - public static final String CURRENT_PROTOCOL_VERSION = "1.0"; - - /** - * Compact constructor that validates required fields. - * - * @param protocolBinding the protocolBinding parameter (see class-level JavaDoc) - * @param url the url parameter (see class-level JavaDoc) - * @param tenant the tenant parameter (see class-level JavaDoc) - * @param protocolVersion the protocolVersion parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if protocolBinding, url, or protocolVersion is null - */ - public AgentInterface { - Assert.checkNotNullParam("protocolBinding", protocolBinding); - Assert.checkNotNullParam("url", url); - Assert.checkNotNullParam("tenant", tenant); - - if (protocolVersion == null || protocolVersion.isEmpty()) { - protocolVersion = CURRENT_PROTOCOL_VERSION; - } - } - - /** - * Convenience constructor for creating an AgentInterface with specified tenant and default protocol version. - * - * @param protocolBinding the protocol binding (see class-level JavaDoc) - * @param url the endpoint URL (see class-level JavaDoc) - * @param tenant the tenant (see class-level JavaDoc) - */ - public AgentInterface(String protocolBinding, String url, String tenant) { - this(protocolBinding, url, tenant, CURRENT_PROTOCOL_VERSION); - } - - /** - * Convenience constructor for creating an AgentInterface with default protocol version and no tenant. - * - * @param protocolBinding the protocol binding (see class-level JavaDoc) - * @param url the endpoint URL (see class-level JavaDoc) - */ - public AgentInterface(String protocolBinding, String url) { - this(protocolBinding, url, "", CURRENT_PROTOCOL_VERSION); - } -} diff --git a/spec/src/main/java/io/a2a/spec/AgentProvider.java b/spec/src/main/java/io/a2a/spec/AgentProvider.java deleted file mode 100644 index b78a7702b..000000000 --- a/spec/src/main/java/io/a2a/spec/AgentProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; - -/** - * Represents information about the organization or entity providing an agent. - *

    - * AgentProvider contains metadata about who is responsible for operating and maintaining - * an agent. This information helps users understand the source and trustworthiness of - * the agent, and provides contact or documentation references. - *

    - * Provider information is included in the {@link AgentCard} to identify the organization - * behind the agent service. - *

    - * This class is immutable. - * - * @param organization the name of the organization providing the agent (required) - * @param url the URL to the provider's website or information page (required) - * @see AgentCard - * @see A2A Protocol Specification - */ -public record AgentProvider(String organization, String url) { - - /** - * Compact constructor that validates required fields. - * - * @param organization the organization parameter (see class-level JavaDoc) - * @param url the url parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if organization or url is null - */ - public AgentProvider { - Assert.checkNotNullParam("organization", organization); - Assert.checkNotNullParam("url", url); - } -} diff --git a/spec/src/main/java/io/a2a/spec/AgentSkill.java b/spec/src/main/java/io/a2a/spec/AgentSkill.java deleted file mode 100644 index 2bddf57bf..000000000 --- a/spec/src/main/java/io/a2a/spec/AgentSkill.java +++ /dev/null @@ -1,247 +0,0 @@ -package io.a2a.spec; - -import java.util.List; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Represents a distinct skill or capability that an agent can perform in the A2A Protocol. - *

    - * An AgentSkill defines a specific operation or category of operations that the agent supports. - * Skills provide a structured way to advertise what an agent can do, helping clients discover - * and invoke appropriate functionality. Each skill is uniquely identified and includes metadata - * about supported input/output modes, examples, and security requirements. - *

    - * Key Components: - *

      - *
    • Identity: Unique ID and human-readable name for discovery and invocation
    • - *
    • Documentation: Description, examples, and tags for understanding usage
    • - *
    • Modes: Supported input/output formats (text, audio, image, etc.)
    • - *
    • Security: Specific authentication/authorization requirements for this skill
    • - *
    - *

    - * Skills are declared in the {@link AgentCard} and represent the agent's advertised capabilities. - * Clients can query available skills to understand what operations are supported and how to - * invoke them. If inputModes/outputModes are not specified, the skill inherits the defaults - * from the AgentCard. - *

    - * This class is immutable and uses the Builder pattern for construction. - * - * @param id unique identifier for the skill (required, e.g., "weather_query", "translate_text") - * @param name human-readable name of the skill (required, e.g., "Weather Queries") - * @param description detailed explanation of what the skill does and how to use it (required) - * @param tags categorization tags for discovery and filtering (required, may be empty list) - * @param examples example queries or use cases demonstrating the skill (optional) - * @param inputModes supported input formats for this skill (optional, inherits from AgentCard if not set) - * @param outputModes supported output formats for this skill (optional, inherits from AgentCard if not set) - * @param securityRequirements security requirements specific to this skill (optional) - * @see AgentCard - * @see A2A Protocol Specification - */ -public record AgentSkill(String id, String name, String description, List tags, - @Nullable List examples, @Nullable List inputModes, @Nullable List outputModes, - @Nullable List securityRequirements) { - - /** - * Compact constructor that validates required fields. - * - * @param id the id parameter (see class-level JavaDoc) - * @param name the name parameter (see class-level JavaDoc) - * @param description the description parameter (see class-level JavaDoc) - * @param tags the tags parameter (see class-level JavaDoc) - * @param examples the examples parameter (see class-level JavaDoc) - * @param inputModes the inputModes parameter (see class-level JavaDoc) - * @param outputModes the outputModes parameter (see class-level JavaDoc) - * @param securityRequirements the security parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if id, name, description, or tags is null - */ - public AgentSkill { - Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("name", name); - Assert.checkNotNullParam("description", description); - Assert.checkNotNullParam("tags", tags); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing immutable {@link AgentSkill} instances. - *

    - * The Builder pattern provides a fluent API for setting skill properties. - * This approach ensures that once an AgentSkill is created, its state cannot - * be modified, which is important for protocol correctness and thread-safety. - *

    - * Example usage: - *

    {@code
    -     * AgentSkill skill = AgentSkill.builder()
    -     *     .id("weather_query")
    -     *     .name("Weather Queries")
    -     *     .description("Get current weather conditions for any location")
    -     *     .tags(List.of("weather", "information"))
    -     *     .examples(List.of(
    -     *         "What's the weather in Tokyo?",
    -     *         "Current temperature in London"
    -     *     ))
    -     *     .inputModes(List.of("text"))
    -     *     .outputModes(List.of("text"))
    -     *     .build();
    -     * }
    - */ - public static class Builder { - - private @Nullable String id; - private @Nullable String name; - private @Nullable String description; - private @Nullable List tags; - private @Nullable List examples; - private @Nullable List inputModes; - private @Nullable List outputModes; - private @Nullable List securityRequirements; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the unique identifier for the skill. - *

    - * The ID should be a stable identifier that doesn't change across versions, - * typically in snake_case format (e.g., "weather_query", "translate_text"). - * - * @param id the skill ID (required) - * @return this builder for method chaining - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Sets the human-readable name of the skill. - *

    - * The name is displayed to users and should clearly describe the skill's purpose. - * - * @param name the skill name (required) - * @return this builder for method chaining - */ - public Builder name(String name) { - this.name = name; - return this; - } - - /** - * Sets a detailed description of what the skill does and how to use it. - *

    - * The description should provide sufficient information for users to understand - * when and how to invoke the skill. - * - * @param description the skill description (required) - * @return this builder for method chaining - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * Sets categorization tags for discovery and filtering. - *

    - * Tags help organize skills and enable clients to filter or search for - * specific categories of functionality. - * - * @param tags list of tags (required, may be empty) - * @return this builder for method chaining - */ - public Builder tags(List tags) { - this.tags = tags; - return this; - } - - /** - * Sets example queries or use cases demonstrating the skill. - *

    - * Examples help users understand how to phrase requests to effectively - * invoke the skill. - * - * @param examples list of example queries (optional) - * @return this builder for method chaining - */ - public Builder examples(List examples) { - this.examples = examples; - return this; - } - - /** - * Sets the supported input formats for this skill. - *

    - * If not specified, the skill inherits the default input modes from the AgentCard. - * Common values include "text", "audio", "image", "video". - * - * @param inputModes list of supported input formats (optional) - * @return this builder for method chaining - */ - public Builder inputModes(List inputModes) { - this.inputModes = inputModes; - return this; - } - - /** - * Sets the supported output formats for this skill. - *

    - * If not specified, the skill inherits the default output modes from the AgentCard. - * Common values include "text", "audio", "image", "video". - * - * @param outputModes list of supported output formats (optional) - * @return this builder for method chaining - */ - public Builder outputModes(List outputModes) { - this.outputModes = outputModes; - return this; - } - - /** - * Sets security requirements specific to this skill. - *

    - * Security requirements override or supplement the agent-level security - * defined in the AgentCard. Each entry represents an alternative security - * requirement (OR relationship). Schemes within a single SecurityRequirement - * must all be satisfied (AND relationship). - * - * @param securityRequirements list of security requirements (optional) - * @return this builder for method chaining - * @see SecurityRequirement - */ - public Builder securityRequirements(List securityRequirements) { - this.securityRequirements = securityRequirements; - return this; - } - - /** - * Builds an immutable {@link AgentSkill} from the current builder state. - * - * @return a new AgentSkill instance - * @throws IllegalArgumentException if any required field (id, name, description, tags) is null - */ - public AgentSkill build() { - return new AgentSkill( - Assert.checkNotNullParam("id", id), - Assert.checkNotNullParam("name", name), - Assert.checkNotNullParam("description", description), - Assert.checkNotNullParam("tags", tags), - examples, - inputModes, - outputModes, - securityRequirements); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/Artifact.java b/spec/src/main/java/io/a2a/spec/Artifact.java deleted file mode 100644 index 6f9b5dc68..000000000 --- a/spec/src/main/java/io/a2a/spec/Artifact.java +++ /dev/null @@ -1,208 +0,0 @@ -package io.a2a.spec; - -import java.util.List; -import java.util.Map; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Represents a file, data structure, or other resource generated by an agent during task execution. - *

    - * Artifacts are outputs created by agents in response to user requests. They can represent various - * types of content including documents, data structures, analysis results, generated files, or any - * other structured output from agent operations. - *

    - * Each artifact has a unique identifier and contains content through {@link Part}s, which allow - * for multi-modal output (text, files, structured data). Artifacts can include metadata for - * additional context and support protocol extensions. - *

    - * Artifacts are typically delivered to clients through {@link Task} responses or - * {@link TaskArtifactUpdateEvent} events in streaming scenarios. - *

    - * This class is immutable. Use the {@link Builder} for construction. - * - * @param artifactId the unique identifier for this artifact (required) - * @param name the human-readable name of the artifact (optional) - * @param description a brief description of the artifact's purpose or content (optional) - * @param parts the content parts comprising the artifact (required, must not be empty) - * @param metadata additional key-value metadata for the artifact (optional) - * @param extensions protocol extensions used in this artifact (optional) - * @see A2A Protocol Specification - */ -public record Artifact(String artifactId, @Nullable String name, @Nullable String description, List> parts, @Nullable Map metadata, - @Nullable List extensions) { - - /** - * Compact constructor that validates required fields. - * - * @param artifactId the artifactId parameter (see class-level JavaDoc) - * @param name the name parameter (see class-level JavaDoc) - * @param description the description parameter (see class-level JavaDoc) - * @param parts the parts parameter (see class-level JavaDoc) - * @param metadata the metadata parameter (see class-level JavaDoc) - * @param extensions the extensions parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if artifactId or parts is null, or if parts is empty - */ - public Artifact { - Assert.checkNotNullParam("artifactId", artifactId); - Assert.checkNotNullParam("parts", parts); - if (parts.isEmpty()) { - throw new IllegalArgumentException("Parts cannot be empty"); - } - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Create a new Builder initialized with values from an existing Artifact. - *

    - * This builder creates defensive copies of mutable collections to ensure - * that modifications to the builder do not affect the original Artifact. - * - * @param artifact the Artifact to copy values from - * @return the builder - */ - public static Builder builder(Artifact artifact) { - return new Builder(artifact); - } - - /** - * Builder for constructing immutable {@link Artifact} instances. - *

    - * The Builder provides a fluent API for creating artifacts with required and optional fields. - * Artifacts must have an artifactId and non-empty parts list. - *

    - * Example usage: - *

    {@code
    -     * Artifact result = Artifact.builder()
    -     *     .artifactId("artifact-123")
    -     *     .name("Analysis Report")
    -     *     .description("Detailed analysis of user data")
    -     *     .parts(List.of(new TextPart("Report content...", null)))
    -     *     .build();
    -     * }
    - */ - public static class Builder { - private @Nullable String artifactId; - private @Nullable String name; - private @Nullable String description; - private @Nullable List> parts; - private @Nullable Map metadata; - private @Nullable List extensions; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder(){ - } - - /** - * Creates a new Builder initialized with values from an existing Artifact. - * - * @param existingArtifact the Artifact to copy values from - */ - private Builder(Artifact existingArtifact) { - artifactId = existingArtifact.artifactId; - name = existingArtifact.name; - description = existingArtifact.description; - parts = existingArtifact.parts; - metadata = existingArtifact.metadata; - extensions = existingArtifact.extensions; - } - - /** - * Sets the unique identifier for this artifact. - * - * @param artifactId the artifact identifier (required) - * @return this builder for method chaining - */ - public Builder artifactId(String artifactId) { - this.artifactId = artifactId; - return this; - } - - /** - * Sets the human-readable name of the artifact. - * - * @param name the artifact name (optional) - * @return this builder for method chaining - */ - public Builder name(@Nullable String name) { - this.name = name; - return this; - } - - /** - * Sets a brief description of the artifact's purpose or content. - * - * @param description the artifact description (optional) - * @return this builder for method chaining - */ - public Builder description(@Nullable String description) { - this.description = description; - return this; - } - - /** - * Sets the content parts comprising the artifact. - * - * @param parts the list of content parts (required, must not be empty) - * @return this builder for method chaining - */ - public Builder parts(List> parts) { - this.parts = parts; - return this; - } - - /** - * Sets the content parts from varargs. - * - * @param parts the content parts (required, must not be empty) - * @return this builder for method chaining - */ - public Builder parts(Part... parts) { - this.parts = List.of(parts); - return this; - } - - /** - * Sets additional metadata for the artifact. - * - * @param metadata map of metadata key-value pairs (optional) - * @return this builder for method chaining - */ - public Builder metadata(@Nullable Map metadata) { - this.metadata = metadata; - return this; - } - - /** - * Sets the list of protocol extensions used in this artifact. - * - * @param extensions the list of extension identifiers (optional) - * @return this builder for method chaining - */ - public Builder extensions(@Nullable List extensions) { - this.extensions = (extensions == null) ? null : List.copyOf(extensions); - return this; - } - - /** - * Builds a new immutable {@link Artifact} from the current builder state. - * - * @return a new Artifact instance - * @throws IllegalArgumentException if required fields are missing or parts is empty - */ - public Artifact build() { - return new Artifact(Assert.checkNotNullParam("artifactId", artifactId), name, description, Assert.checkNotNullParam("parts", parts), metadata, extensions); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java b/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java deleted file mode 100644 index 29d1201d1..000000000 --- a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.a2a.spec; - - -import io.a2a.util.Assert; - -/** - * Authentication information for agent authentication and push notification endpoints. - *

    - * This record encapsulates authentication schemes and credentials for two primary use cases: - *

      - *
    • Agent Authentication: Clients authenticate to access protected agent resources. - * The {@code scheme} reference a security scheme from {@link AgentCard#securitySchemes()}.
    • - *
    • Push Notification Authentication: Agents authenticate when POSTing task updates to - * client-provided push notification endpoints. Supports HTTP Basic, Bearer tokens, API keys, OAuth.
    • - *
    - * - * @param scheme security scheme name for authentication (required) - * @param credentials optional credentials string (format depends on scheme, e.g., base64-encoded for Basic auth) - * @see AgentCard#securitySchemes() for available security schemes - * @see PushNotificationConfig for push notification configuration - * @see SecurityScheme for security scheme definitions - * @see A2A Protocol Specification - */ -public record AuthenticationInfo(String scheme, String credentials) { - - /** - * Compact constructor that validates required fields. - * - * @param scheme the schemes parameter (see class-level JavaDoc) - * @param credentials the credentials parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if schemes is null - */ - public AuthenticationInfo { - Assert.checkNotNullParam("scheme", scheme); - } -} diff --git a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java b/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java deleted file mode 100644 index d3d399057..000000000 --- a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import io.a2a.util.Assert; - -/** - * Configuration for the OAuth 2.0 Authorization Code flow. - *

    - * The authorization code flow is the most secure OAuth 2.0 flow, recommended for - * server-side applications. It involves redirecting the user to an authorization - * server, obtaining an authorization code, and then exchanging that code for an - * access token. - *

    - * This flow is suitable when the client can securely store client credentials - * and the authorization code can be exchanged server-side. - * - * @param authorizationUrl URL for the authorization endpoint where users authenticate (required) - * @param refreshUrl URL for obtaining refresh tokens (optional) - * @param scopes map of available OAuth scopes to their descriptions (required) - * @param tokenUrl URL for the token endpoint where codes are exchanged for tokens (required) - * @param pkceRequired Indicates if PKCE (RFC 7636) is required for this flow. (required) - * @see OAuthFlows for the container of all supported OAuth flows - * @see OAuth2SecurityScheme for the security scheme using these flows - * @see RFC 6749 - Authorization Code Grant - * @see A2A Protocol Specification - */ -public record AuthorizationCodeOAuthFlow(String authorizationUrl, String refreshUrl, Map scopes, - String tokenUrl, boolean pkceRequired) { - - /** - * Compact constructor that validates required fields. - * - * @param authorizationUrl the authorizationUrl parameter (see class-level JavaDoc) - * @param refreshUrl the refreshUrl parameter (see class-level JavaDoc) - * @param scopes the scopes parameter (see class-level JavaDoc) - * @param tokenUrl the tokenUrl parameter (see class-level JavaDoc) - * @param pkceRequired Indicates if PKCE (RFC 7636) is required for this flow. (required) - * @throws IllegalArgumentException if authorizationUrl, scopes, or tokenUrl is null - */ - public AuthorizationCodeOAuthFlow { - Assert.checkNotNullParam("authorizationUrl", authorizationUrl); - Assert.checkNotNullParam("scopes", scopes); - Assert.checkNotNullParam("tokenUrl", tokenUrl); - } -} diff --git a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java b/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java deleted file mode 100644 index f248eaa70..000000000 --- a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.a2a.spec; - - -import java.util.Map; - -import io.a2a.util.Assert; - -/** - * Configuration for the OAuth 2.0 Client Credentials flow. - *

    - * The client credentials flow is designed for machine-to-machine authentication - * where the client application authenticates using its own credentials (client ID - * and secret) rather than on behalf of a user. This is suitable for server-to-server - * communication and backend services. - *

    - * This flow is appropriate when the client is acting on its own behalf, not - * representing a user, such as accessing its own resources or performing - * administrative operations. - * - * @param refreshUrl URL for obtaining refresh tokens (optional, rarely used in client credentials flow) - * @param scopes map of available OAuth scopes to their descriptions (required) - * @param tokenUrl URL for the token endpoint where client credentials are exchanged for tokens (required) - * @see OAuthFlows for the container of all supported OAuth flows - * @see OAuth2SecurityScheme for the security scheme using these flows - * @see RFC 6749 - Client Credentials Grant - * @see A2A Protocol Specification - */ -public record ClientCredentialsOAuthFlow(String refreshUrl, Map scopes, String tokenUrl) { - - /** - * Compact constructor that validates required fields. - * - * @param refreshUrl the refreshUrl parameter (see class-level JavaDoc) - * @param scopes the scopes parameter (see class-level JavaDoc) - * @param tokenUrl the tokenUrl parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if scopes or tokenUrl is null - */ - public ClientCredentialsOAuthFlow { - Assert.checkNotNullParam("scopes", scopes); - Assert.checkNotNullParam("tokenUrl", tokenUrl); - } - -} diff --git a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java deleted file mode 100644 index 57a88c17c..000000000 --- a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * A2A Protocol error indicating incompatibility between requested content types and agent capabilities. - *

    - * This error is returned when the input or output modes requested by a client are not supported - * by the agent. Agents declare their supported content types via {@link AgentCard#defaultInputModes()} - * and {@link AgentCard#defaultOutputModes()}, and clients can request specific modes via - * {@link MessageSendConfiguration}. - *

    - * Common scenarios: - *

      - *
    • Client requests audio input but agent only supports text
    • - *
    • Client requires video output but agent only produces text and images
    • - *
    • Incompatible combinations of input and output modes
    • - *
    - *

    - * Corresponds to A2A-specific error code {@code -32005}. - *

    - * Usage example: - *

    {@code
    - * if (!agentCard.defaultInputModes().contains(requestedInputMode)) {
    - *     throw new ContentTypeNotSupportedError(
    - *         null,
    - *         "Input mode " + requestedInputMode + " not supported",
    - *         null
    - *     );
    - * }
    - * }
    - * - * @see AgentCard#defaultInputModes() for agent input capabilities - * @see AgentCard#defaultOutputModes() for agent output capabilities - * @see MessageSendConfiguration for client content type preferences - * @see A2A Protocol Specification - */ -public class ContentTypeNotSupportedError extends A2AProtocolError { - - /** - * Constructs a content type not supported error. - * - * @param code the error code - * @param message the error message - * @param data additional error data - */ - public ContentTypeNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super(defaultIfNull(code, CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE), - defaultIfNull(message, "Incompatible content types"), - data, - "https://a2a-protocol.org/errors/content-type-not-supported"); - } -} diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/io/a2a/spec/DataPart.java deleted file mode 100644 index 0e41bec23..000000000 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.a2a.spec; - - -import io.a2a.util.Assert; -import java.util.Map; -import org.jspecify.annotations.Nullable; - - -/** - * Represents a structured data content part within a {@link Message} or {@link Artifact}. - *

    - * DataPart contains arbitrary JSON data for machine-to-machine communication. - * It is used when content needs to be processed programmatically rather than displayed as text, - * such as API responses, configuration data, analysis results, or structured metadata. - *

    - * The data can be any valid JSON value: - *

      - *
    • JSON objects: {@code Map}
    • - *
    • JSON arrays: {@code List} - *
    • Primitives: {@code String}, {@code Number}, {@code Boolean}
    • - *
    • Null values: {@code null}
    • - * - *

      - * Example usage: - *

      {@code
      - * // JSON object
      - * DataPart obj = new DataPart(Map.of(
      - *     "status", "success",
      - *     "count", 42,
      - *     "items", List.of("item1", "item2")
      - * ));
      - *
      - * // JSON array
      - * DataPart array = new DataPart(List.of("item1", "item2", "item3"));
      - *
      - * // Primitive value
      - * DataPart primitive = new DataPart(42);
      - * }
      - * - * @param data the structured data (required, supports JSON objects, arrays, primitives, and null) - * @param metadata additional metadata for the part - * @see Part - * @see Message - * @see Artifact - */ -public record DataPart(Object data, @Nullable Map metadata) implements Part { - - /** - * The JSON member name discriminator for data parts: "data". - *

      - * In protocol v1.0+, this constant defines the JSON member name used for serialization: - * {@code { "data": { "data": { "temperature": 22.5, "unit": "C" } } }} - */ - public static final String DATA = "data"; - - /** - * Compact constructor with validation. - *

      - * Note: For mutable data types (Map, List), callers should ensure immutability - * by using {@code Map.copyOf()} or {@code List.copyOf()} before passing to this constructor. - * - * @param data the structured data (supports JSON objects, arrays, primitives, and null) - * @throws IllegalArgumentException if data is null - */ - public DataPart (Object data, @Nullable Map metadata) { - Assert.checkNotNullParam("data", data); - this.metadata = metadata == null ? null : Map.copyOf(metadata); - this.data = data; - } - - /** - * Constructor. - * - * @param data the structured data (supports JSON objects, arrays, primitives, and not null) - * @throws IllegalArgumentException if data is null - */ - public DataPart(Object data) { - this(data, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java deleted file mode 100644 index 12d6c0624..000000000 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java +++ /dev/null @@ -1,118 +0,0 @@ -package io.a2a.spec; - - - -import io.a2a.util.Assert; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -/** - * Parameters for deleting a push notification configuration from a task. - *

      - * This record specifies which task and which specific push notification configuration - * to remove, allowing cleanup of notification endpoints that are no longer needed. - * - * @param taskId the task identifier (required) - * @param id the specific configuration ID to delete (required) - * @param tenant optional tenant, provided as a path parameter. - * @see A2A Protocol Specification - */ -public record DeleteTaskPushNotificationConfigParams(String taskId, String id, String tenant) { - - /** - * Compact constructor that validates required fields. - * - * @param taskId the taskId parameter (see class-level JavaDoc) - * @param id the id parameter (see class-level JavaDoc) - * @param tenant the tenant parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if taskId or id is null - */ - public DeleteTaskPushNotificationConfigParams { - Assert.checkNotNullParam("taskId", taskId); - Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("tenant", tenant); - } - - /** - * Creates parameters without optional metadata. - * - * @param taskId the task identifier (required) - * @param id the configuration ID to delete (required) - * @throws IllegalArgumentException if taskId or id is null - */ - public DeleteTaskPushNotificationConfigParams(String taskId, String id) { - this(taskId, id, ""); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link DeleteTaskPushNotificationConfigParams} instances. - *

      - * Provides a fluent API for setting parameters with optional metadata. - */ - public static class Builder { - @Nullable String taskId; - @Nullable String id; - @Nullable String tenant; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the task identifier. - * - * @param taskId the task ID (required) - * @return this builder for method chaining - */ - public Builder taskId(String taskId) { - this.taskId = taskId; - return this; - } - - /** - * Sets the push notification configuration ID to delete. - * - * @param id the configuration ID (required) - * @return this builder for method chaining - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Sets optional tenant for the request. - * - * @param tenant arbitrary tenant (optional) - * @return this builder for method chaining - */ - public Builder tenant(String tenant) { - this.tenant = tenant; - return this; - } - - /** - * Builds a new {@link DeleteTaskPushNotificationConfigParams} from the current builder state. - * - * @return a new DeleteTaskPushNotificationConfigParams instance - * @throws IllegalArgumentException if taskId or id is null - */ - public DeleteTaskPushNotificationConfigParams build() { - return new DeleteTaskPushNotificationConfigParams( - Assert.checkNotNullParam("taskId", taskId), - Assert.checkNotNullParam("id", id), - Utils.defaultIfNull(tenant,"")); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java b/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java deleted file mode 100644 index d2d25c047..000000000 --- a/spec/src/main/java/io/a2a/spec/DeviceCodeOAuthFlow.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import io.a2a.util.Assert; - -/** - * Configuration details for the OAuth 2.0 Device Code flow (RFC 8628). - *

      - * This flow is designed for input-constrained devices such as IoT devices, - * and CLI tools where the user authenticates on a separate device. - * - * @param deviceAuthorizationUrl the device authorization endpoint URL (required) - * @param tokenUrl URL for the token endpoint where credentials are exchanged for tokens (required) - * @param refreshUrl URL for obtaining refresh tokens (optional) - * @param scopes map of available OAuth scopes to their descriptions (required) - * @see OAuthFlows for the container of all supported OAuth flows - * @see OAuth2SecurityScheme for the security scheme using these flows - * @see A2A Protocol Specification - */ -public record DeviceCodeOAuthFlow(String deviceAuthorizationUrl, String tokenUrl, String refreshUrl, Map scopes) { - - /** - * Compact constructor that validates required fields. - * - * @param deviceAuthorizationUrl the device authorization endpoint URL (required) - * @param tokenUrl URL for the token endpoint where credentials are exchanged for tokens (required) - * @param refreshUrl URL for obtaining refresh tokens (optional) - * @param scopes map of available OAuth scopes to their descriptions (required) - * @throws IllegalArgumentException if authorizationUrl, scopes, or tokenUrl is null - */ - public DeviceCodeOAuthFlow { - Assert.checkNotNullParam("deviceAuthorizationUrl", deviceAuthorizationUrl); - Assert.checkNotNullParam("tokenUrl", tokenUrl); - Assert.checkNotNullParam("scopes", scopes); - } -} diff --git a/spec/src/main/java/io/a2a/spec/Event.java b/spec/src/main/java/io/a2a/spec/Event.java deleted file mode 100644 index 2be6a757f..000000000 --- a/spec/src/main/java/io/a2a/spec/Event.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.a2a.spec; - -/** - * Marker interface for all event types in the A2A Protocol. - *

      - * Events are the fundamental communication mechanism for agent task execution and state updates. - * They enable both synchronous request-response patterns and asynchronous streaming updates. - *

      - * The Event hierarchy includes: - *

        - *
      • {@link EventKind} - Events that can be returned from non-streaming operations
      • - *
      • {@link StreamingEventKind} - Events that can be emitted during streaming responses
      • - *
      • {@link UpdateEvent} - Incremental update events for task progress
      • - *
      - *

      - * Common event types include: - *

        - *
      • {@link Task} - Complete task state
      • - *
      • {@link Message} - Message exchange
      • - *
      • {@link TaskStatusUpdateEvent} - Task status changes
      • - *
      • {@link TaskArtifactUpdateEvent} - Artifact creation/updates
      • - *
      - * - * @see EventKind - * @see StreamingEventKind - * @see UpdateEvent - */ -public interface Event { -} diff --git a/spec/src/main/java/io/a2a/spec/EventKind.java b/spec/src/main/java/io/a2a/spec/EventKind.java deleted file mode 100644 index a9713859b..000000000 --- a/spec/src/main/java/io/a2a/spec/EventKind.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.a2a.spec; - -/** - * Interface for events that can be returned from non-streaming A2A Protocol operations. - *

      - * EventKind represents events that are suitable for synchronous request-response patterns. - * These events provide complete state information and are typically returned as the final - * result of an operation. - *

      - * EventKind implementations use polymorphic JSON serialization where the JSON member name - * itself acts as the type discriminator (e.g., "task", "message"). - *

      - * Permitted implementations: - *

        - *
      • {@link Task} - Complete task state with status and artifacts
      • - *
      • {@link Message} - Full message with all content parts
      • - *
      - * - * @see StreamingEventKind - * @see Event - */ -public interface EventKind { - - /** - * Returns the type identifier for this event. - *

      - * This method provides programmatic type discrimination for routing, logging, and debugging. - * NOTE: This value is NOT serialized to JSON in protocol v1.0+. - * - * @return the event kind string (e.g., "task", "message") - */ - String kind(); -} diff --git a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java b/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java deleted file mode 100644 index 5b961e2bf..000000000 --- a/spec/src/main/java/io/a2a/spec/ExtendedAgentCardNotConfiguredError.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - - -/** - * A2A Protocol error indicating that the agent does not have an authenticated extended card configured. - *

      - * This error is returned when a client attempts to retrieve an authenticated extended agent card, - * but the agent has not configured authentication-protected extended card information. - *

      - * Extended cards may contain additional agent metadata, capabilities, or configuration that - * should only be accessible to authenticated clients. Agents that don't implement this feature - * will return this error. - *

      - * Corresponds to A2A-specific error code {@code -32007}. - *

      - * Usage example: - *

      {@code
      - * // In agent implementation
      - * if (extendedAgentCard == null) {
      - *     throw new ExtendedAgentCardNotConfiguredError();
      - * }
      - * }
      - * - * @see AgentCard for the base agent card structure - * @see A2A Protocol Specification - */ -public class ExtendedAgentCardNotConfiguredError extends A2AProtocolError { - - /** - * Constructs an error for agents that don't support authenticated extended card retrieval. - * - * @param code the error code - * @param message the error message - * @param data additional error data - */ - public ExtendedAgentCardNotConfiguredError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, EXTENDED_AGENT_CARD_NOT_CONFIGURED_ERROR_CODE), - defaultIfNull(message, "Extended Card not configured"), - data, - "https://a2a-protocol.org/errors/extended-agent-card-not-configured"); - } -} diff --git a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java b/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java deleted file mode 100644 index abb11aa9f..000000000 --- a/spec/src/main/java/io/a2a/spec/ExtensionSupportRequiredError.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.EXTENSION_SUPPORT_REQUIRED_ERROR; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - - -/** - * A2A Protocol error indicating that a client requested use of an extension marked as required - * but did not declare support for it. - *

      - * This error is returned when a client attempts to use a feature or capability that requires - * a specific extension, but the client has not declared support for that extension in the request. - * Extensions marked as {@code required: true} in the Agent Card must be explicitly supported - * by the client. - *

      - * Corresponds to A2A-specific error code {@code -32008}. - *

      - * Usage example: - *

      {@code
      - * // In agent implementation
      - * if (requiredExtension && !clientSupportsExtension) {
      - *     throw new ExtensionSupportRequiredError(null,
      - *         "Extension 'custom-auth' is required but not supported by client", null);
      - * }
      - * }
      - * - * @see AgentCard for extension declarations - * @see A2A Protocol Specification - */ -public class ExtensionSupportRequiredError extends A2AProtocolError { - - /** - * Constructs an error when a client requests a required extension without declaring support. - * - * @param code the error code (defaults to -32008 if null) - * @param message the error message (defaults to standard message if null) - * @param data additional error data (optional) - */ - public ExtensionSupportRequiredError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, EXTENSION_SUPPORT_REQUIRED_ERROR), - defaultIfNull(message, "Extension support required but not declared"), - data, - "https://a2a-protocol.org/errors/extension-support-required"); - } -} diff --git a/spec/src/main/java/io/a2a/spec/FileContent.java b/spec/src/main/java/io/a2a/spec/FileContent.java deleted file mode 100644 index f258e3eb5..000000000 --- a/spec/src/main/java/io/a2a/spec/FileContent.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.a2a.spec; - -/** - * Sealed interface representing file content in the A2A Protocol. - *

      - * FileContent provides a polymorphic abstraction for file data, allowing files to be - * represented either as embedded binary content or as URI references. This flexibility - * enables different strategies for file transmission based on size, security, and - * accessibility requirements. - *

      - * The sealed interface permits only two implementations: - *

        - *
      • {@link FileWithBytes} - File content embedded as base64-encoded bytes (for small files or inline data)
      • - *
      • {@link FileWithUri} - File content referenced by URI (for large files or external resources)
      • - *
      - *

      - * Both implementations must provide: - *

        - *
      • MIME type - Describes the file format (e.g., "image/png", "application/pdf")
      • - *
      • File name - The original or display name for the file
      • - *
      - * - * @see FilePart - * @see FileWithBytes - * @see FileWithUri - */ -public sealed interface FileContent permits FileWithBytes, FileWithUri { - - /** - * Returns the MIME type of the file content. - * - * @return the MIME type (e.g., "image/png", "text/plain", "application/json") - */ - String mimeType(); - - /** - * Returns the file name. - * - * @return the file name (e.g., "document.pdf", "image.jpg") - */ - String name(); -} diff --git a/spec/src/main/java/io/a2a/spec/FilePart.java b/spec/src/main/java/io/a2a/spec/FilePart.java deleted file mode 100644 index 8deec1e7d..000000000 --- a/spec/src/main/java/io/a2a/spec/FilePart.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.a2a.spec; - - -import io.a2a.util.Assert; -import java.util.Map; -import org.jspecify.annotations.Nullable; - - -/** - * Represents a file content part within a {@link Message} or {@link Artifact}. - *

      - * FilePart contains file data that can be provided in two ways: - *

        - *
      • {@link FileWithBytes} - File content embedded as base64-encoded bytes
      • - *
      • {@link FileWithUri} - File content referenced by URI
      • - *
      - *

      - * File parts are used to exchange binary data, documents, images, or any file-based content - * between users and agents. The choice between bytes and URI depends on file size, accessibility, - * and security requirements. - *

      - * Example usage: - *

      {@code
      - * // File with embedded bytes
      - * FilePart imageBytes = new FilePart(
      - *     new FileWithBytes("image/png", "diagram.png", "iVBORw0KGgoAAAANS...")
      - * );
      - *
      - * // File with URI reference
      - * FilePart imageUri = new FilePart(
      - *     new FileWithUri("image/png", "photo.png", "https://example.com/photo.png")
      - * );
      - * }
      - * - * @param file the file content (required, either FileWithBytes or FileWithUri) - * @param metadata additional metadata for the part - * @see Part - * @see FileContent - * @see FileWithBytes - * @see FileWithUri - */ -public record FilePart(FileContent file, @Nullable Map metadata) implements Part { - - /** - * The JSON member name discriminator for file parts: "file". - *

      - * In protocol v1.0+, this constant defines the JSON member name used for serialization: - * {@code { "file": { "mediaType": "image/png", "name": "photo.png", ... } }} - */ - public static final String FILE = "file"; - - /** - * Compact constructor with validation. - * - * @param file the file content (required, either FileWithBytes or FileWithUri) - * @throws IllegalArgumentException if file is null - */ - public FilePart (FileContent file, @Nullable Map metadata) { - Assert.checkNotNullParam("file", file); - this.metadata = metadata == null ? null : Map.copyOf(metadata); - this.file = file; - } - - /** - * Constructor. - * - * @param file the file content (required, either FileWithBytes or FileWithUri) - * @throws IllegalArgumentException if file is null - */ - public FilePart (FileContent file) { - this(file, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/FileWithBytes.java b/spec/src/main/java/io/a2a/spec/FileWithBytes.java deleted file mode 100644 index b5aef3813..000000000 --- a/spec/src/main/java/io/a2a/spec/FileWithBytes.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.a2a.spec; - -/** - * Represents file content embedded directly as base64-encoded bytes. - *

      - * FileWithBytes is used when file content needs to be transmitted inline with the message or - * artifact, rather than requiring a separate download. This is appropriate for: - *

        - *
      • Small files that fit comfortably in a JSON payload
      • - *
      • Generated content that doesn't exist as a standalone file
      • - *
      • Content that must be preserved exactly as created
      • - *
      • Scenarios where URI accessibility is uncertain
      • - *
      - *

      - * The bytes field contains the base64-encoded file content. Decoders should handle the base64 - * encoding/decoding transparently. - *

      - * This class is immutable. - * - * @param mimeType the MIME type of the file (e.g., "image/png", "application/pdf") (required) - * @param name the file name (e.g., "report.pdf", "diagram.png") (required) - * @param bytes the base64-encoded file content (required) - * @see FileContent - * @see FilePart - * @see FileWithUri - */ -public record FileWithBytes(String mimeType, String name, String bytes) implements FileContent { -} diff --git a/spec/src/main/java/io/a2a/spec/FileWithUri.java b/spec/src/main/java/io/a2a/spec/FileWithUri.java deleted file mode 100644 index b3fb72363..000000000 --- a/spec/src/main/java/io/a2a/spec/FileWithUri.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.a2a.spec; - -/** - * Represents file content referenced by a URI location. - *

      - * FileWithUri is used when file content is stored externally and accessed via a URI reference. - * This is appropriate for: - *

        - *
      • Large files that would be impractical to embed in JSON
      • - *
      • Publicly accessible resources (HTTP/HTTPS URLs)
      • - *
      • Files stored in object storage (S3, Azure Blob, etc.)
      • - *
      • Content that may be accessed multiple times or by multiple clients
      • - *
      - *

      - * The URI should be accessible to the receiving party. Considerations include: - *

        - *
      • Authentication requirements for private resources
      • - *
      • URI expiration for temporary access (signed URLs)
      • - *
      • Network accessibility and firewall rules
      • - *
      - *

      - * This class is immutable. - * - * @param mimeType the MIME type of the file (e.g., "image/png", "application/pdf") (required) - * @param name the file name (e.g., "report.pdf", "photo.jpg") (required) - * @param uri the URI where the file content can be accessed (e.g., "https://example.com/file.pdf") (required) - * @see FileContent - * @see FilePart - * @see FileWithBytes - */ -public record FileWithUri(String mimeType, String name, String uri) implements FileContent { -} - diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java deleted file mode 100644 index f51063bcf..000000000 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java +++ /dev/null @@ -1,115 +0,0 @@ -package io.a2a.spec; - - - -import io.a2a.util.Assert; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -/** - * Parameters for retrieving push notification configuration for a specific task. - *

      - * This record specifies which task's push notification configuration to retrieve, with - * an optional filter by configuration ID if multiple configurations exist for the task. - * - * @param taskId the task identifier (required) - * @param id optional specific configuration ID to retrieve - * @param tenant optional tenant, provided as a path parameter. - * @see TaskPushNotificationConfig for the returned configuration structure - * @see A2A Protocol Specification - */ -public record GetTaskPushNotificationConfigParams(String taskId, String id, String tenant) { - - /** - * Compact constructor that validates required fields. - * - * @param taskId the taskId parameter (see class-level JavaDoc) - * @param id the id parameter (see class-level JavaDoc) - * @param tenant the tenant parameter (see class-level JavaDoc) - * @throws IllegalArgumentException if taskId or tenant is null - */ - public GetTaskPushNotificationConfigParams { - Assert.checkNotNullParam("taskId", taskId); - Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("tenant", tenant); - } - - /** - * Convenience constructor for creating parameters without tenant. - * - * @param taskId the task identifier (required) - * @param id optional configuration ID to retrieve - */ - public GetTaskPushNotificationConfigParams(String taskId, String id) { - this(taskId, id, ""); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing GetTaskPushNotificationConfigParams instances. - */ - public static class Builder { - @Nullable String taskId; - @Nullable String id; - @Nullable String tenant; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the task ID. - * - * @param taskId the task ID - * @return this builder for method chaining - */ - public Builder taskId(String taskId) { - this.taskId = taskId; - return this; - } - - /** - * Sets the push notification configuration ID. - * - * @param id the configuration ID - * @return this builder for method chaining - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Sets the tenant. - * - * @param tenant the tenant - * @return this builder for method chaining - */ - public Builder tenant(String tenant) { - this.tenant = tenant; - return this; - } - - /** - * Builds the parameters instance. - * - * @return a new GetTaskPushNotificationConfigParams - */ - public GetTaskPushNotificationConfigParams build() { - return new GetTaskPushNotificationConfigParams( - Assert.checkNotNullParam("taskId", taskId), - Assert.checkNotNullParam("id", id), - Utils.defaultIfNull(tenant,"")); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java b/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java deleted file mode 100644 index a34c64239..000000000 --- a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java +++ /dev/null @@ -1,130 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * HTTP authentication security scheme for agent authentication. - *

      - * This security scheme uses HTTP authentication mechanisms, supporting both basic authentication - * and bearer token authentication (e.g., JWT). The {@code scheme} parameter specifies the - * HTTP authentication scheme name as defined in RFC 7235. - *

      - * Common schemes: - *

        - *
      • {@code basic} - HTTP Basic authentication (RFC 7617)
      • - *
      • {@code bearer} - Bearer token authentication (RFC 6750), typically used with OAuth 2.0
      • - *
      - *

      - * For bearer tokens, the {@code bearerFormat} field can provide additional information about - * the token format (e.g., "JWT"). - *

      - * Example usage: - *

      {@code
      - * HTTPAuthSecurityScheme scheme = HTTPAuthSecurityScheme.builder()
      - *     .scheme("bearer")
      - *     .bearerFormat("JWT")
      - *     .description("JWT bearer token authentication")
      - *     .build();
      - * }
      - * - * @param bearerFormat the bearer token format (optional) - * @param scheme the authentication scheme (required) - * @param description the scheme description (optional) - * @see SecurityScheme for the base interface - * @see OpenAPI Security Scheme - * @see RFC 7235 - HTTP Authentication - * @see A2A Protocol Specification - */ -public record HTTPAuthSecurityScheme(@Nullable String bearerFormat, String scheme, @Nullable String description) implements SecurityScheme { - - /** The HTTP security scheme type identifier. */ - public static final String TYPE = "httpAuthSecurityScheme"; - - /** - * Compact constructor with validation. - * - * @param bearerFormat the bearer token format (optional) - * @param scheme the authentication scheme (required) - * @param description the scheme description (optional) - * @throws IllegalArgumentException if scheme is null - */ - public HTTPAuthSecurityScheme { - Assert.checkNotNullParam("scheme", scheme); - } - - @Override - public String type() { - return TYPE; - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link HTTPAuthSecurityScheme} instances. - *

      - * Provides a fluent API for creating HTTP authentication security schemes. - * The {@code scheme} parameter is required and must be set before calling {@code build()}. - */ - public static class Builder { - private @Nullable String bearerFormat; - private @Nullable String scheme; - private @Nullable String description; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the bearer token format hint. - * - * @param bearerFormat hint to the client about the format of bearer tokens (e.g., "JWT") - * @return this builder instance - */ - public Builder bearerFormat(String bearerFormat) { - this.bearerFormat = bearerFormat; - return this; - } - - /** - * Sets the HTTP authentication scheme name. - * - * @param scheme the scheme name (required, e.g., "basic" or "bearer") - * @return this builder instance - */ - public Builder scheme(String scheme) { - this.scheme = scheme; - return this; - } - - /** - * Sets an optional description of the security scheme. - * - * @param description human-readable description - * @return this builder instance - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * Builds the {@link HTTPAuthSecurityScheme} instance. - * - * @return a new immutable HTTPAuthSecurityScheme - * @throws IllegalArgumentException if required fields are missing - */ - public HTTPAuthSecurityScheme build() { - return new HTTPAuthSecurityScheme(bearerFormat, Assert.checkNotNullParam("scheme", scheme), description); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/InternalError.java b/spec/src/main/java/io/a2a/spec/InternalError.java deleted file mode 100644 index 5d9793972..000000000 --- a/spec/src/main/java/io/a2a/spec/InternalError.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - - -/** - * JSON-RPC error indicating an internal error occurred on the server. - *

      - * This error represents unexpected server-side failures such as unhandled exceptions, - * resource exhaustion, or other internal issues that prevent the server from processing - * a request. This is a catch-all error for server problems not covered by more specific - * error types. - *

      - * Corresponds to JSON-RPC 2.0 error code {@code -32603}. - *

      - * Usage example: - *

      {@code
      - * try {
      - *     // Server processing
      - * } catch (Exception e) {
      - *     throw new InternalError("Failed to process request: " + e.getMessage());
      - * }
      - * }
      - * - * @see JSON-RPC 2.0 Error Codes - */ -public class InternalError extends A2AError { - - /** - * Constructs an internal error with full parameters. - * - * @param code the error code - * @param message the error message - * @param data additional error data - */ - public InternalError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, INTERNAL_ERROR_CODE), - defaultIfNull(message, "Internal Error"), - data); - } - - /** - * Constructs an internal error with a message. - * - * @param message the error message - */ - public InternalError(@Nullable String message) { - this(null, message, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java deleted file mode 100644 index d6d8508d9..000000000 --- a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - - -/** - * A2A Protocol error indicating that an agent returned a response not conforming to protocol specifications. - *

      - * This error is typically raised by client implementations when validating agent responses. - * It indicates that the agent's response structure, content, or format violates the A2A Protocol - * requirements for the invoked method. - *

      - * Common violations: - *

        - *
      • Missing required fields in response objects
      • - *
      • Invalid field types or values
      • - *
      • Malformed event stream data
      • - *
      • Response doesn't match declared agent capabilities
      • - *
      - *

      - * Corresponds to A2A-specific error code {@code -32006}. - *

      - * Usage example: - *

      {@code
      - * SendMessageResponse response = client.sendMessage(request);
      - * if (response.task() == null) {
      - *     throw new InvalidAgentResponseError(
      - *         null,
      - *         "Response missing required 'task' field",
      - *         null
      - *     );
      - * }
      - * }
      - * - * @see A2A Protocol Specification - */ -public class InvalidAgentResponseError extends A2AProtocolError { - - /** - * Constructs an invalid agent response error. - * - * @param code the error code - * @param message the error message - * @param data additional error data - */ - public InvalidAgentResponseError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, INVALID_AGENT_RESPONSE_ERROR_CODE), - defaultIfNull(message, "Invalid agent response"), - data, - "https://a2a-protocol.org/errors/invalid-agent-response"); - } -} diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java deleted file mode 100644 index a56f1ac91..000000000 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java +++ /dev/null @@ -1,64 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * JSON-RPC error indicating that method parameters are invalid or missing required fields. - *

      - * This error is returned when a JSON-RPC method is called with parameters that fail validation. - * Common causes include: - *

        - *
      • Missing required parameters
      • - *
      • Parameters of incorrect type
      • - *
      • Parameter values outside acceptable ranges
      • - *
      • Malformed parameter structures
      • - *
      - *

      - * Corresponds to JSON-RPC 2.0 error code {@code -32602}. - *

      - * Usage example: - *

      {@code
      - * // Default error with standard message
      - * throw new InvalidParamsError();
      - *
      - * // Custom error message
      - * throw new InvalidParamsError("taskId parameter is required");
      - * }
      - * - * @see JSON-RPC 2.0 Error Codes - */ -public class InvalidParamsError extends A2AError { - - /** - * Constructs an invalid params error with full parameters. - * - * @param code the error code - * @param message the error message - * @param data additional error data - */ - public InvalidParamsError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, INVALID_PARAMS_ERROR_CODE), - defaultIfNull(message, "Invalid parameters"), - data); - } - - /** - * Constructs an invalid params error with a message. - * - * @param message the error message - */ - public InvalidParamsError(@Nullable String message) { - this(null, message, null); - } - - /** - * Constructs an invalid params error with default message. - */ - public InvalidParamsError() { - this(null, null, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java deleted file mode 100644 index 512c21b59..000000000 --- a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - - -/** - * JSON-RPC error indicating that the request payload is not a valid JSON-RPC Request object. - *

      - * This error is returned when the JSON-RPC request fails structural validation. - * Common causes include: - *

        - *
      • Missing required JSON-RPC fields (jsonrpc, method, id)
      • - *
      • Invalid JSON-RPC version (must be "2.0")
      • - *
      • Malformed request structure
      • - *
      • Type mismatches in required fields
      • - *
      - *

      - * Corresponds to JSON-RPC 2.0 error code {@code -32600}. - *

      - * Usage example: - *

      {@code
      - * // Default error with standard message
      - * throw new InvalidRequestError();
      - *
      - * // Custom error message
      - * throw new InvalidRequestError("Missing 'method' field in request");
      - * }
      - * - * @see JSON-RPC 2.0 Error Codes - */ -public class InvalidRequestError extends A2AError { - - /** - * Constructs an invalid request error with default message. - */ - public InvalidRequestError() { - this(null, null, null); - } - - /** - * Constructs an invalid request error with full parameters. - * - * @param code the error code - * @param message the error message - * @param data additional error data - */ - public InvalidRequestError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, INVALID_REQUEST_ERROR_CODE), - defaultIfNull(message, "Request payload validation error"), - data); - } - - /** - * Constructs an invalid request error with a message. - * - * @param message the error message - */ - public InvalidRequestError(String message) { - this(null, message, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/JSONParseError.java b/spec/src/main/java/io/a2a/spec/JSONParseError.java deleted file mode 100644 index 72e4aaf02..000000000 --- a/spec/src/main/java/io/a2a/spec/JSONParseError.java +++ /dev/null @@ -1,62 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * JSON-RPC error indicating that the server received invalid JSON that could not be parsed. - *

      - * This error is returned when the request payload is not valid JSON, such as malformed syntax, - * unexpected tokens, or encoding issues. This is distinct from {@link InvalidRequestError}, - * which indicates structurally valid JSON that doesn't conform to the JSON-RPC specification. - *

      - * Corresponds to JSON-RPC 2.0 error code {@code -32700}. - *

      - * Usage example: - *

      {@code
      - * try {
      - *     objectMapper.readValue(payload, JSONRPCRequest.class);
      - * } catch (io.a2a.json.JsonProcessingException e) {
      - *     throw new JSONParseError("Malformed JSON: " + e.getMessage());
      - * }
      - * }
      - * - * @see A2AError for the base error class - * @see A2AError for the error marker interface - * @see InvalidRequestError for structurally valid but invalid requests - * @see JSON-RPC 2.0 Error Codes - */ -public class JSONParseError extends A2AError { - - /** - * Constructs a JSON parse error with default message. - */ - public JSONParseError() { - this(null, null, null); - } - - /** - * Constructs a JSON parse error with a message. - * - * @param message the error message - */ - public JSONParseError(String message) { - this(null, message, null); - } - - /** - * Constructs a JSON parse error with full parameters. - * - * @param code the error code - * @param message the error message - * @param data additional error data - */ - public JSONParseError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, JSON_PARSE_ERROR_CODE), - defaultIfNull(message, "Invalid JSON payload"), - data); - } -} diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java deleted file mode 100644 index f24f3c4ce..000000000 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java +++ /dev/null @@ -1,140 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -/** - * Parameters for listing all push notification configurations for a task. - *

      - * This record specifies which task's push notification configurations to list, returning - * all configured notification endpoints for that task. - * - * @param id the task identifier (required) - * @param tenant optional tenant, provided as a path parameter. - * @param pageSize the maximum number of items to return per page - * @param pageToken the pagination token for the next page - * @see TaskPushNotificationConfig for the configuration structure - * @see A2A Protocol Specification - */ -public record ListTaskPushNotificationConfigParams(String id, int pageSize, String pageToken, String tenant) { - - /** - * Compact constructor for validation. - * Validates that required parameters are not null. - * @param id the task identifier - * @param pageSize the maximum number of items to return per page - * @param pageToken the pagination token for the next page - * @param tenant the tenant identifier - * @throws IllegalArgumentException if id or tenant is null - */ - public ListTaskPushNotificationConfigParams { - Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("tenant", tenant); - } - - /** - * Convenience constructor with default tenant. - * - * @param id the task identifier (required) - */ - public ListTaskPushNotificationConfigParams(String id) { - this(id, 0, "", ""); - } - - /** - * Validates and returns the effective page size (between 1 and 100, defaults to 100). - * - * @return the effective page size - */ - public int getEffectivePageSize() { - if (pageSize <= 0 || pageSize > 100) { - return 100; - } - return pageSize; - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private @Nullable String id; - private @Nullable Integer pageSize; - private @Nullable String pageToken; - private @Nullable String tenant; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the id. - * - * @param id the task identifier (required) - * @return this builder for method chaining - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Sets the pageSize. - * - * @param pageSize the maximum number of items to return per page - * @return this builder for method chaining - */ - public Builder pageSize(Integer pageSize) { - this.pageSize = pageSize; - return this; - } - - /** - * Sets the pageToken. - * - * @param pageToken the pagination token for the next page - * @return this builder for method chaining - */ - public Builder pageToken(String pageToken) { - this.pageToken = pageToken; - return this; - } - - /** - * Sets the tenant. - * - * @param tenant the tenant identifier - * @return this builder for method chaining - */ - public Builder tenant(String tenant) { - this.tenant = tenant; - return this; - } - - /** - * Builds the ListTaskPushNotificationConfigParams. - * - * @return a new ListTaskPushNotificationConfigParams instance - * @throws IllegalArgumentException if id is null - */ - public ListTaskPushNotificationConfigParams build() { - return new ListTaskPushNotificationConfigParams( - Assert.checkNotNullParam("id", id), - pageSize != null ? pageSize : 0, - pageToken != null ? pageToken : "", - Utils.defaultIfNull(tenant,"") - ); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java deleted file mode 100644 index 1ae125713..000000000 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java +++ /dev/null @@ -1,63 +0,0 @@ -package io.a2a.spec; - -import java.util.List; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Result of listing push notification configurations for a task with pagination support. - * - * @param configs List of push notification configurations for the task - * @param nextPageToken Token for retrieving the next page of results (null if no more results) - */ -public record ListTaskPushNotificationConfigResult(List configs, - @Nullable String nextPageToken) { - /** - * Compact constructor for validation. - * Validates parameters and creates a defensive copy of the configs list. - * - * @param configs the list of push notification configurations - * @param nextPageToken token for next page - * @throws IllegalArgumentException if validation fails - */ - public ListTaskPushNotificationConfigResult { - Assert.checkNotNullParam("configs", configs); - // Make defensive copy - configs = List.copyOf(configs); - } - - /** - * Constructor for results without pagination. - * - * @param configs the list of push notification configurations - */ - public ListTaskPushNotificationConfigResult(List configs) { - this(configs, null); - } - - /** - * Returns whether there are more results available. - * - * @return true if there are more pages of results - */ - public boolean hasMoreResults() { - return nextPageToken != null && !nextPageToken.isEmpty(); - } - - /** - * Return the size of the configs. - * @return the size of the configs. - */ - public int size() { - return configs.size(); - } - - /** - * Return if the configs is empty or not. - * @return true if the configs is empty - false otherwise. - */ - public boolean isEmpty() { - return configs.isEmpty(); - } -} diff --git a/spec/src/main/java/io/a2a/spec/ListTasksParams.java b/spec/src/main/java/io/a2a/spec/ListTasksParams.java deleted file mode 100644 index 3a1680af9..000000000 --- a/spec/src/main/java/io/a2a/spec/ListTasksParams.java +++ /dev/null @@ -1,233 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import java.time.Instant; - -import org.jspecify.annotations.Nullable; - -/** - * Parameters for listing tasks with optional filtering and pagination. - * - * @param contextId Filter tasks by context ID to get tasks from a specific conversation or session - * @param status Filter tasks by their current status state - * @param pageSize Maximum number of tasks to return (1-100, defaults to 50) - * @param pageToken Token for pagination from a previous ListTasksResult - * @param historyLength Number of recent messages to include in each task's history (defaults to 0) - * @param statusTimestampAfter Filter tasks updated after this timestamp - * @param includeArtifacts Whether to include artifacts in the returned tasks (defaults to false) - * @param tenant optional tenant, provided as a path parameter. - */ -public record ListTasksParams( - @Nullable String contextId, - @Nullable TaskState status, - @Nullable Integer pageSize, - @Nullable String pageToken, - @Nullable Integer historyLength, - @Nullable Instant statusTimestampAfter, - @Nullable Boolean includeArtifacts, - String tenant -) { - private static final int MIN_PAGE_SIZE = 1; - private static final int MAX_PAGE_SIZE = 100; - private static final int DEFAULT_PAGE_SIZE = 50; - /** - * Compact constructor for validation. - * Validates that the tenant parameter is not null and parameters are within valid ranges. - * - * @param contextId filter by context ID - * @param status filter by task status - * @param pageSize maximum number of results per page - * @param pageToken pagination token - * @param historyLength number of history items to include - * @param statusTimestampAfter filter by status timestamp - * @param includeArtifacts whether to include artifacts - * @param tenant the tenant identifier - * @throws InvalidParamsError if tenant is null or if pageSize or historyLength are out of valid range - */ - public ListTasksParams { - Assert.checkNotNullParam("tenant", tenant); - // Validate pageSize (1-100) - if (pageSize != null && (pageSize < MIN_PAGE_SIZE || pageSize > MAX_PAGE_SIZE)) { - throw new InvalidParamsError(null, - "pageSize must be between " + MIN_PAGE_SIZE + " and " + MAX_PAGE_SIZE + ", got: " + pageSize, null); - } - - // Validate historyLength (>= 0) - if (historyLength != null && historyLength < 0) { - throw new InvalidParamsError(null, - "historyLength must be non-negative, got: " + historyLength, null); - } - } - /** - * Default constructor for listing all tasks. - */ - public ListTasksParams() { - this(null, null, null, null, null, null, null, ""); - } - - /** - * Constructor with pagination. - * - * @param pageSize Maximum number of tasks to return - * @param pageToken Token for pagination - */ - public ListTasksParams(Integer pageSize, String pageToken) { - this(null, null, pageSize, pageToken, null, null, null, ""); - } - - /** - * Returns the effective page size (defaults to 50 if not specified). - * Values are validated in the constructor to be within the range [1, 100]. - * - * @return the effective page size - */ - public int getEffectivePageSize() { - return pageSize != null ? pageSize : DEFAULT_PAGE_SIZE; - } - - /** - * Returns the effective history length (defaults to 0 if not specified). - * Values are validated in the constructor to be non-negative. - * - * @return the effective history length - */ - public int getEffectiveHistoryLength() { - return historyLength != null ? historyLength : 0; - } - - /** - * Returns whether to include artifacts (defaults to false). - * - * @return true if artifacts should be included - */ - public boolean shouldIncludeArtifacts() { - return includeArtifacts != null && includeArtifacts; - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private @Nullable String contextId; - private @Nullable TaskState status; - private @Nullable Integer pageSize; - private @Nullable String pageToken; - private @Nullable Integer historyLength; - private @Nullable Instant statusTimestampAfter; - private @Nullable Boolean includeArtifacts; - private @Nullable String tenant; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the contextId. - * - * @param contextId the contextId - * @return this builder for method chaining - */ - public Builder contextId(String contextId) { - this.contextId = contextId; - return this; - } - - /** - * Sets the status. - * - * @param status the status - * @return this builder for method chaining - */ - public Builder status(TaskState status) { - this.status = status; - return this; - } - - /** - * Sets the pageSize. - * - * @param pageSize the pageSize - * @return this builder for method chaining - */ - public Builder pageSize(Integer pageSize) { - this.pageSize = pageSize; - return this; - } - - /** - * Sets the pageToken. - * - * @param pageToken the pageToken - * @return this builder for method chaining - */ - public Builder pageToken(String pageToken) { - this.pageToken = pageToken; - return this; - } - - /** - * Sets the historyLength. - * - * @param historyLength the historyLength - * @return this builder for method chaining - */ - public Builder historyLength(Integer historyLength) { - this.historyLength = historyLength; - return this; - } - - /** - * Sets the statusTimestampAfter. - * - * @param statusTimestampAfter the statusTimestampAfter - * @return this builder for method chaining - */ - public Builder statusTimestampAfter(Instant statusTimestampAfter) { - this.statusTimestampAfter = statusTimestampAfter; - return this; - } - - /** - * Sets the includeArtifacts. - * - * @param includeArtifacts the includeArtifacts - * @return this builder for method chaining - */ - public Builder includeArtifacts(Boolean includeArtifacts) { - this.includeArtifacts = includeArtifacts; - return this; - } - - /** - * Sets the tenant. - * - * @param tenant the tenant - * @return this builder for method chaining - */ - public Builder tenant(String tenant) { - this.tenant = tenant; - return this; - } - - /** - * Builds the ListTasksParams. - * - * @return a new ListTasksParams instance - */ - public ListTasksParams build() { - return new ListTasksParams(contextId, status, pageSize, pageToken, historyLength, - statusTimestampAfter, includeArtifacts, tenant == null ? "" : tenant); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/Message.java b/spec/src/main/java/io/a2a/spec/Message.java deleted file mode 100644 index 4459fd5b7..000000000 --- a/spec/src/main/java/io/a2a/spec/Message.java +++ /dev/null @@ -1,299 +0,0 @@ -package io.a2a.spec; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Represents a single message in the conversation between a user and an agent in the A2A Protocol. - *

      - * A Message encapsulates communication content exchanged during agent interactions. It contains the - * message role (user or agent), content parts (text, files, or data), and contextual metadata for - * message threading and correlation. - *

      - * Messages are fundamental to the A2A Protocol's conversational model, enabling rich multi-modal - * communication between users and agents. Each message has a unique identifier and can reference - * related tasks and contexts. - *

      - * Messages implement both {@link EventKind} and {@link StreamingEventKind}, meaning they can be - * sent as standalone events or as part of a streaming response sequence. - *

      - * This class is mutable (allows setting taskId and contextId) to support post-construction correlation - * with tasks and conversation contexts. Use the {@link Builder} for construction. - * - * @param role the role of the message sender (user or agent) - * @param parts the content parts of the message (text, file, or data) - * @param messageId the unique identifier for this message - * @param contextId the conversation context identifier - * @param taskId the task identifier this message is associated with - * @param referenceTaskIds list of reference task identifiers - * @param metadata additional metadata for the message - * @param extensions list of protocol extensions used in this message - * @see A2A Protocol Specification - */ -public record Message(Role role, List> parts, - String messageId, - @Nullable String contextId, - @Nullable String taskId, - @Nullable List referenceTaskIds, - @Nullable Map metadata, - @Nullable List extensions - ) implements EventKind, StreamingEventKind { - - /** - * The identifier when used in streaming responses - */ - public static final String STREAMING_EVENT_ID = "message"; - - /** - * Compact constructor with validation and defensive copying. - * - * @param role the role of the message sender (user or agent) - * @param parts the content parts of the message (text, file, or data) - * @param messageId the unique identifier for this message - * @param contextId the conversation context identifier - * @param taskId the task identifier this message is associated with - * @param referenceTaskIds list of reference task identifiers - * @param metadata additional metadata for the message - * @param extensions list of protocol extensions used in this message - * @throws IllegalArgumentException if role, parts, or messageId is null, or if parts is empty - */ - public Message { - Assert.checkNotNullParam("role", role); - Assert.checkNotNullParam("parts", parts); - Assert.checkNotNullParam("messageId", messageId); - if (parts.isEmpty()) { - throw new IllegalArgumentException("Parts cannot be empty"); - } - parts = List.copyOf(parts); - referenceTaskIds = referenceTaskIds != null ? List.copyOf(referenceTaskIds) : null; - metadata = (metadata != null) ? Map.copyOf(metadata) : null; - extensions = extensions != null ? List.copyOf(extensions) : null; - } - - @Override - public String kind() { - return STREAMING_EVENT_ID; - } - - /** - * Creates a new Builder for constructing Message instances. - * - * @return a Message.builder instance - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Creates a new Builder initialized with values from an existing Message. - * - * @param message the Message to copy values from - * @return a new Builder instance initialized with the message's values - */ - public static Builder builder(Message message) { - return new Builder(message); - } - - /** - * Defines the role of the message sender in the conversation. - *

      - * The role determines who originated the message and how it should be processed - * within the conversational context. - */ - public enum Role { - /** - * Message originated from the user (client side). - */ - ROLE_USER, - /** - * Message originated from the agent (server side). - */ - ROLE_AGENT, - /** - * Unspecified role. - */ - ROLE_UNSPECIFIED; - } - - /** - * Builder for constructing {@link Message} instances with fluent API. - *

      - * The Builder provides a convenient way to construct messages with required and optional fields. - * If messageId is not provided, a random UUID will be generated automatically. - *

      - * Example usage: - *

      {@code
      -     * Message userMessage = Message.builder()
      -     *     .role(Message.Role.USER)
      -     *     .parts(List.of(new TextPart("Hello, agent!")))
      -     *     .contextId("conv-123")
      -     *     .build();
      -     * }
      - */ - public static class Builder { - - private @Nullable - Role role; - private @Nullable - List> parts; - private @Nullable - String messageId; - private @Nullable - String contextId; - private @Nullable - String taskId; - private @Nullable - List referenceTaskIds; - private @Nullable - Map metadata; - private @Nullable - List extensions; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Creates a new Builder initialized with values from an existing Message. - * - * @param message the Message to copy values from - */ - private Builder(Message message) { - role = message.role(); - parts = message.parts(); - messageId = message.messageId(); - contextId = message.contextId(); - taskId = message.taskId(); - referenceTaskIds = message.referenceTaskIds(); - metadata = message.metadata(); - extensions = message.extensions(); - } - - /** - * Sets the role of the message sender. - * - * @param role the message role (required) - * @return this builder for method chaining - */ - public Builder role(Role role) { - this.role = role; - return this; - } - - /** - * Sets the content parts of the message. - * - * @param parts the list of message parts (required, must not be empty) - * @return this builder for method chaining - */ - public Builder parts(List> parts) { - this.parts = parts; - return this; - } - - /** - * Sets the content parts of the message from varargs. - * - * @param parts the message parts (required, must not be empty) - * @return this builder for method chaining - */ - public Builder parts(Part... parts) { - this.parts = List.of(parts); - return this; - } - - /** - * Sets the unique identifier for this message. - *

      - * If not provided, a random UUID will be generated when {@link #build()} is called. - * - * @param messageId the message identifier (optional) - * @return this builder for method chaining - */ - public Builder messageId(String messageId) { - this.messageId = messageId; - return this; - } - - /** - * Sets the conversation context identifier. - * - * @param contextId the context identifier (optional) - * @return this builder for method chaining - */ - public Builder contextId(String contextId) { - this.contextId = contextId; - return this; - } - - /** - * Sets the task identifier this message is associated with. - * - * @param taskId the task identifier (optional) - * @return this builder for method chaining - */ - public Builder taskId(String taskId) { - this.taskId = taskId; - return this; - } - - /** - * Sets the list of reference task identifiers this message relates to. - * - * @param referenceTaskIds the list of reference task IDs (optional) - * @return this builder for method chaining - */ - public Builder referenceTaskIds(List referenceTaskIds) { - this.referenceTaskIds = referenceTaskIds; - return this; - } - - /** - * Sets additional metadata for the message. - * - * @param metadata map of metadata key-value pairs (optional) - * @return this builder for method chaining - */ - public Builder metadata(@Nullable Map metadata) { - this.metadata = metadata; - return this; - } - - /** - * Sets the list of protocol extensions used in this message. - * - * @param extensions the list of extension identifiers (optional) - * @return this builder for method chaining - */ - public Builder extensions(List extensions) { - this.extensions = (extensions == null) ? null : List.copyOf(extensions); - return this; - } - - /** - * Builds a new {@link Message} from the current builder state. - *

      - * If messageId was not set, a random UUID will be generated. - * - * @return a new Message instance - * @throws IllegalArgumentException if required fields are missing or invalid - */ - public Message build() { - return new Message( - Assert.checkNotNullParam("role", role), - Assert.checkNotNullParam("parts", parts), - messageId == null ? UUID.randomUUID().toString() : messageId, - contextId, - taskId, - referenceTaskIds, - metadata, - extensions); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java deleted file mode 100644 index d8ea772a9..000000000 --- a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java +++ /dev/null @@ -1,131 +0,0 @@ -package io.a2a.spec; - -import java.util.List; - -import org.jspecify.annotations.NonNull; -import org.jspecify.annotations.Nullable; - -/** - * Configuration options for {@code message/send} and {@code message/stream} requests. - *

      - * This record defines how the agent should process a message request, including output format - * preferences, conversation history context, push notification settings, and blocking behavior. - *

      - * All fields are optional and have sensible defaults when not specified. - * - * @param acceptedOutputModes list of output modes the client can handle (e.g., "text", "audio") - * @param historyLength number of previous messages to include in conversation context (must be non-negative) - * @param pushNotificationConfig configuration for asynchronous push notifications when task state changes - * @param blocking whether the request should block until task completion (defaults to false) - * @see MessageSendParams for the parameters that use this configuration - * @see PushNotificationConfig for push notification options - * @see A2A Protocol Specification - */ -public record MessageSendConfiguration(@Nullable List acceptedOutputModes, @Nullable Integer historyLength, - @Nullable PushNotificationConfig pushNotificationConfig, Boolean blocking) { - - /** - * Compact constructor for validation. - * Validates that historyLength is non-negative if provided. - * - * @param acceptedOutputModes list of accepted output modes - * @param historyLength maximum number of history items - * @param pushNotificationConfig push notification configuration - * @param blocking whether the request should block - * @throws IllegalArgumentException if historyLength is negative - */ - public MessageSendConfiguration { - if (historyLength != null && historyLength < 0) { - throw new IllegalArgumentException("Invalid history length"); - } - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link MessageSendConfiguration} instances. - *

      - * Provides a fluent API for configuring message send behavior with sensible defaults. - */ - public static class Builder { - - @Nullable List acceptedOutputModes; - @Nullable Integer historyLength; - @Nullable PushNotificationConfig pushNotificationConfig; - Boolean blocking = false; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the accepted output modes. - * - * @param acceptedOutputModes list of output modes the client can handle - * @return this builder - */ - public Builder acceptedOutputModes(List acceptedOutputModes) { - this.acceptedOutputModes = acceptedOutputModes; - return this; - } - - /** - * Sets the push notification configuration. - * - * @param pushNotificationConfig configuration for push notifications - * @return this builder - */ - public Builder pushNotificationConfig(@Nullable PushNotificationConfig pushNotificationConfig) { - this.pushNotificationConfig = pushNotificationConfig; - return this; - } - - /** - * Sets the conversation history length. - * - * @param historyLength number of previous messages to include (must be non-negative) - * @return this builder - * @throws IllegalArgumentException if historyLength is negative - */ - public Builder historyLength(@Nullable Integer historyLength) { - if (historyLength != null && historyLength < 0) { - throw new IllegalArgumentException("Invalid history length"); - } - this.historyLength = historyLength; - return this; - } - - /** - * Sets whether the request should block until completion. - * - * @param blocking true to block until task completes, false for fire-and-forget - * @return this builder - */ - public Builder blocking(@NonNull Boolean blocking) { - this.blocking = blocking; - return this; - } - - /** - * Builds the {@link MessageSendConfiguration}. - * - * @return a new message send configuration instance - */ - public MessageSendConfiguration build() { - return new MessageSendConfiguration( - acceptedOutputModes, - historyLength, - pushNotificationConfig, - blocking); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/MessageSendParams.java b/spec/src/main/java/io/a2a/spec/MessageSendParams.java deleted file mode 100644 index e1c75a668..000000000 --- a/spec/src/main/java/io/a2a/spec/MessageSendParams.java +++ /dev/null @@ -1,137 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Parameters for sending a message to an agent in the A2A Protocol. - *

      - * This record encapsulates the message content, optional configuration, and metadata for - * agent task requests. It is used to define what message to send and how to process it. - *

      - * The message can create a new task, continue an existing task (if it contains a task ID), - * or restart a task depending on the agent's implementation and the message context. - * - * @param message the message to send to the agent (required) - * @param configuration optional configuration for message processing behavior - * @param metadata optional arbitrary key-value metadata for the request - * @param tenant optional tenant, provided as a path parameter. - * @see MessageSendConfiguration for available configuration options - * @see A2A Protocol Specification - */ -public record MessageSendParams(Message message, @Nullable MessageSendConfiguration configuration, - @Nullable Map metadata, String tenant) { - - /** - * Compact constructor for validation. - * Validates that required parameters are not null. - * - * @param message the message to send - * @param configuration optional message send configuration - * @param metadata optional metadata - * @param tenant the tenant identifier - */ - public MessageSendParams { - Assert.checkNotNullParam("message", message); - Assert.checkNotNullParam("tenant", tenant); - } - - /** - * Convenience constructor with default tenant. - * - * @param message the message to send (required) - * @param configuration optional configuration for message processing - * @param metadata optional metadata - */ - public MessageSendParams(Message message, @Nullable MessageSendConfiguration configuration, @Nullable Map metadata) { - this(message, configuration, metadata, ""); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link MessageSendParams} instances. - *

      - * Provides a fluent API for building message send parameters with optional - * configuration and metadata. - */ - public static class Builder { - @Nullable Message message; - @Nullable MessageSendConfiguration configuration; - @Nullable Map metadata; - @Nullable String tenant; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the message to send to the agent. - * - * @param message the message (required) - * @return this builder - */ - public Builder message(Message message) { - this.message = message; - return this; - } - - /** - * Sets the optional configuration for message processing. - * - * @param configuration the message send configuration - * @return this builder - */ - public Builder configuration(@Nullable MessageSendConfiguration configuration) { - this.configuration = configuration; - return this; - } - - /** - * Sets optional metadata for the request. - * - * @param metadata arbitrary key-value metadata - * @return this builder - */ - public Builder metadata(@Nullable Map metadata) { - this.metadata = metadata; - return this; - } - - /** - * Sets optional tenant for the request. - * - * @param tenant arbitrary key-value metadata - * @return this builder - */ - public Builder tenant(String tenant) { - this.tenant = tenant; - return this; - } - - /** - * Builds the {@link MessageSendParams}. - * - * @return a new message send parameters instance - * @throws IllegalArgumentException if message is null - */ - public MessageSendParams build() { - return new MessageSendParams( - Assert.checkNotNullParam("message", message), - configuration, - metadata, - tenant == null ? "" : tenant); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java deleted file mode 100644 index c69aaa572..000000000 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * JSON-RPC error indicating that the requested method does not exist or is not available. - *

      - * This error is returned when a client attempts to invoke a JSON-RPC method that is not - * implemented by the agent. In the A2A Protocol context, this typically means calling - * an unsupported protocol method. - *

      - * Corresponds to JSON-RPC 2.0 error code {@code -32601}. - *

      - * Usage example: - *

      {@code
      - * // Standard error for unknown method
      - * throw new MethodNotFoundError();
      - * }
      - * - * @see JSON-RPC 2.0 Error Codes - */ -public class MethodNotFoundError extends A2AError { - - /** - * Constructs error with all parameters. - * - * @param code the error code (defaults to -32601 if null) - * @param message the error message (defaults to "Method not found" if null) - * @param data additional error data (optional) - */ - public MethodNotFoundError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, METHOD_NOT_FOUND_ERROR_CODE), - defaultIfNull(message, "Method not found"), - data); - } - - /** - * Constructs error with default message. - */ - public MethodNotFoundError() { - this(METHOD_NOT_FOUND_ERROR_CODE, null, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java b/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java deleted file mode 100644 index 7210e1db7..000000000 --- a/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.a2a.spec; - -/** - * Mutual TLS (mTLS) security scheme for agent authentication. - *

      - * This security scheme uses mutual TLS authentication, where both the client and server - * present X.509 certificates to authenticate each other. This provides strong, - * certificate-based authentication at the transport layer. - *

      - * Unlike other authentication schemes that operate at the HTTP layer, mTLS authentication - * occurs during the TLS handshake before any HTTP communication begins. This makes it - * particularly suitable for high-security environments and machine-to-machine communication. - *

      - * Example usage: - *

      {@code
      - * MutualTLSSecurityScheme scheme = new MutualTLSSecurityScheme(
      - *     "Client certificate authentication required"
      - * );
      - * }
      - * - * @param description optional description of the security scheme - * @see SecurityScheme for the base interface - * @see OpenAPI Security Scheme - * @see RFC 8446 - TLS 1.3 Client Authentication - * @see A2A Protocol Specification - */ -public record MutualTLSSecurityScheme(String description) implements SecurityScheme { - - /** - * The type identifier for mutual TLS security schemes: "mtlsSecurityScheme". - */ - public static final String TYPE = "mtlsSecurityScheme"; - - @Override - public String type() { - return TYPE; - } -} diff --git a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java b/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java deleted file mode 100644 index 85e0f76cb..000000000 --- a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java +++ /dev/null @@ -1,124 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * OAuth 2.0 security scheme for agent authentication. - *

      - * This security scheme uses OAuth 2.0 authorization flows to authenticate requests. - * Supports authorization code, client credentials, implicit, and password flows - * via the {@link OAuthFlows} configuration. - *

      - * Corresponds to the OpenAPI "oauth2" security scheme type. - * - * @param flows the OAuth 2.0 flow configuration (required) - * @param description optional description of the security scheme - * @param oauth2MetadataUrl optional URL to OAuth 2.0 metadata (RFC 8414) - * @see SecurityScheme for the base interface - * @see OAuthFlows for flow configuration - * @see OpenAPI Security Scheme - * @see A2A Protocol Specification - */ -public record OAuth2SecurityScheme(OAuthFlows flows, @Nullable String description, @Nullable String oauth2MetadataUrl) - implements SecurityScheme { - - /** - * The type identifier for OAuth 2.0 security schemes: "oauth2SecurityScheme". - */ - public static final String TYPE = "oauth2SecurityScheme"; - - /** - * Compact constructor with validation. - * - * @param flows the OAuth 2.0 flow configuration (required) - * @param description optional description of the security scheme - * @param oauth2MetadataUrl optional URL to OAuth 2.0 metadata (RFC 8414) - * @throws IllegalArgumentException if flows is null - */ - public OAuth2SecurityScheme { - Assert.checkNotNullParam("flows", flows); - } - - @Override - public String type() { - return TYPE; - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing immutable {@link OAuth2SecurityScheme} instances. - *

      - * Example usage: - *

      {@code
      -     * OAuth2SecurityScheme scheme = OAuth2SecurityScheme.builder()
      -     *     .flows(flows)
      -     *     .description("OAuth 2.0 authentication")
      -     *     .oauth2MetadataUrl("https://example.com/.well-known/oauth-authorization-server")
      -     *     .build();
      -     * }
      - */ - public static class Builder { - - private @Nullable OAuthFlows flows; - private @Nullable String description; - private @Nullable String oauth2MetadataUrl; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the OAuth flows configuration. - * - * @param flows the OAuth 2.0 flow configuration (required) - * @return this builder for method chaining - */ - public Builder flows(OAuthFlows flows) { - this.flows = flows; - return this; - } - - /** - * Sets the human-readable description of the security scheme. - * - * @param description the description (optional) - * @return this builder for method chaining - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * Sets the OAuth 2.0 metadata URL. - * - * @param oauth2MetadataUrl URL to OAuth 2.0 metadata document (RFC 8414) (optional) - * @return this builder for method chaining - */ - public Builder oauth2MetadataUrl(String oauth2MetadataUrl) { - this.oauth2MetadataUrl = oauth2MetadataUrl; - return this; - } - - /** - * Builds a new immutable {@link OAuth2SecurityScheme} from the current builder state. - * - * @return a new OAuth2SecurityScheme instance - * @throws IllegalArgumentException if flows is null - */ - public OAuth2SecurityScheme build() { - return new OAuth2SecurityScheme(Assert.checkNotNullParam("flows", flows), description, oauth2MetadataUrl); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/OAuthFlows.java b/spec/src/main/java/io/a2a/spec/OAuthFlows.java deleted file mode 100644 index 4349c4906..000000000 --- a/spec/src/main/java/io/a2a/spec/OAuthFlows.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.a2a.spec; - -import org.jspecify.annotations.Nullable; - -/** - * Configuration for supported OAuth 2.0 authorization flows. - *

      - * This record specifies which OAuth 2.0 flows the agent supports and their configurations, - * including authorization and token endpoints, scopes, and refresh URLs. - *

      - * All fields are optional; only the flows supported by the agent should be specified. - * - * @param authorizationCode OAuth 2.0 authorization code flow configuration - * @param clientCredentials OAuth 2.0 client credentials flow configuration - * @param deviceCode OAuth 2.0 device code flow configuration - * @see OAuth2SecurityScheme for the security scheme using these flows - * @see OpenAPI OAuth Flows Object - * @see A2A Protocol Specification - */ -public record OAuthFlows(@Nullable AuthorizationCodeOAuthFlow authorizationCode, @Nullable ClientCredentialsOAuthFlow clientCredentials, - @Nullable DeviceCodeOAuthFlow deviceCode) { - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing {@link OAuthFlows} instances. - */ - public static class Builder { - private @Nullable AuthorizationCodeOAuthFlow authorizationCode; - private @Nullable ClientCredentialsOAuthFlow clientCredentials; - private @Nullable DeviceCodeOAuthFlow deviceCode; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the authorization code flow configuration. - * - * @param authorizationCode the authorization code flow (optional) - * @return this builder for method chaining - */ - public Builder authorizationCode(AuthorizationCodeOAuthFlow authorizationCode) { - this.authorizationCode = authorizationCode; - return this; - } - - /** - * Sets the client credentials flow configuration. - * - * @param clientCredentials the client credentials flow (optional) - * @return this builder for method chaining - */ - public Builder clientCredentials(ClientCredentialsOAuthFlow clientCredentials) { - this.clientCredentials = clientCredentials; - return this; - } - - /** - * Sets the device code flow configuration. - * - * @param deviceCode the device code flow (optional) - * @return this builder for method chaining - */ - public Builder deviceCode(DeviceCodeOAuthFlow deviceCode) { - this.deviceCode = deviceCode; - return this; - } - - - /** - * Builds a new immutable OAuthFlows instance. - * - * @return a new OAuthFlows instance - */ - public OAuthFlows build() { - return new OAuthFlows(authorizationCode, clientCredentials, deviceCode); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java b/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java deleted file mode 100644 index 371f18982..000000000 --- a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java +++ /dev/null @@ -1,112 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * OpenID Connect security scheme for agent authentication. - *

      - * This security scheme uses OpenID Connect Discovery to automatically configure - * authentication. The {@code openIdConnectUrl} must point to an OpenID Connect - * Discovery document that describes the provider's configuration, including - * authorization and token endpoints. - *

      - * OpenID Connect builds on OAuth 2.0 to provide identity layer functionality, - * enabling clients to verify user identity and obtain basic profile information. - *

      - * Example usage: - *

      {@code
      - * OpenIdConnectSecurityScheme scheme = OpenIdConnectSecurityScheme.builder()
      - *     .openIdConnectUrl("https://example.com/.well-known/openid-configuration")
      - *     .description("OpenID Connect authentication")
      - *     .build();
      - * }
      - * - * @param openIdConnectUrl URL to the OpenID Connect Discovery document (required) - * @param description optional description of the security scheme - * @see SecurityScheme for the base interface - * @see OpenAPI Security Scheme - * @see OpenID Connect Discovery - * @see A2A Protocol Specification - */ -public record OpenIdConnectSecurityScheme(String openIdConnectUrl, @Nullable String description) implements SecurityScheme { - - /** - * The type identifier for OpenID Connect security schemes: "openIdConnect". - */ - public static final String TYPE = "openIdConnectSecurityScheme"; - - /** - * Compact constructor with validation. - * - * @param openIdConnectUrl URL to the OpenID Connect Discovery document (required) - * @param description optional description of the security scheme - * @throws IllegalArgumentException if openIdConnectUrl is null - */ - public OpenIdConnectSecurityScheme { - Assert.checkNotNullParam("openIdConnectUrl", openIdConnectUrl); - } - - @Override - public String type() { - return TYPE; - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing immutable {@link OpenIdConnectSecurityScheme} instances. - *

      - * Provides a fluent API for creating OpenID Connect security schemes. - * The {@code openIdConnectUrl} parameter is required. - */ - public static class Builder { - private @Nullable String openIdConnectUrl; - private @Nullable String description; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the OpenID Connect Discovery URL. - * - * @param openIdConnectUrl URL to the OpenID Connect Discovery document (required) - * @return this builder for method chaining - */ - public Builder openIdConnectUrl(String openIdConnectUrl) { - this.openIdConnectUrl = openIdConnectUrl; - return this; - } - - /** - * Sets the human-readable description of the security scheme. - * - * @param description the description (optional) - * @return this builder for method chaining - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * Builds a new immutable {@link OpenIdConnectSecurityScheme} from the current builder state. - * - * @return a new OpenIdConnectSecurityScheme instance - * @throws IllegalArgumentException if openIdConnectUrl is null - */ - public OpenIdConnectSecurityScheme build() { - return new OpenIdConnectSecurityScheme(Assert.checkNotNullParam("openIdConnectUrl", openIdConnectUrl), description); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/Part.java b/spec/src/main/java/io/a2a/spec/Part.java deleted file mode 100644 index 631f87f88..000000000 --- a/spec/src/main/java/io/a2a/spec/Part.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.a2a.spec; - -/** - * Base interface for content parts within {@link Message}s and {@link Artifact}s. - *

      - * Parts represent the fundamental content units in the A2A Protocol, allowing multi-modal - * communication through different content types. A Part can be: - *

        - *
      • {@link TextPart} - Plain text content
      • - *
      • {@link FilePart} - File content (as bytes or URI reference)
      • - *
      • {@link DataPart} - Structured data (JSON objects)
      • - *
      - *

      - * Parts use polymorphic JSON serialization where the JSON member name itself acts as the - * type discriminator (e.g., "text", "file", "data"). This aligns with Protocol Buffers' - * oneof semantics and modern API design practices. - *

      - * Use {@code instanceof} pattern matching to determine the concrete Part type at runtime: - *

      {@code
      - * if (part instanceof TextPart textPart) {
      - *     String text = textPart.text();
      - * } else if (part instanceof FilePart filePart) {
      - *     FileContent file = filePart.file();
      - * }
      - * }
      - * - * @param the type of content contained in this part - * @see Message - * @see Artifact - * @see A2A Protocol Specification - */ -public interface Part { - // No methods - use instanceof for type discrimination -} \ No newline at end of file diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java deleted file mode 100644 index d6c88dec5..000000000 --- a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java +++ /dev/null @@ -1,145 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Configuration for asynchronous push notifications of task updates. - *

      - * This record defines the endpoint and authentication details for receiving task event - * notifications. When configured, the agent will POST task updates (status changes, - * artifact additions, completions) to the specified URL as they occur, enabling - * asynchronous workflows without polling. - *

      - * Authentication can be provided via either: - *

        - *
      • Simple bearer token in the {@code token} field
      • - *
      • More complex authentication via {@link AuthenticationInfo}
      • - *
      - * - * @param url the HTTP/HTTPS endpoint URL to receive push notifications (required) - * @param token optional bearer token for simple authentication - * @param authentication optional complex authentication configuration - * @param id optional client-provided identifier for this configuration - * @see AuthenticationInfo for authentication details - * @see TaskPushNotificationConfig for task-specific bindings - * @see MessageSendConfiguration for configuring push notifications on message send - * @see A2A Protocol Specification - */ -public record PushNotificationConfig(String url, @Nullable String token, @Nullable AuthenticationInfo authentication, @Nullable String id) { - - /** - * Compact constructor for validation. - * Validates that the URL is not null. - * - * @param url the notification endpoint URL - * @param token optional bearer token - * @param authentication optional authentication info - * @param id optional configuration identifier - */ - public PushNotificationConfig { - Assert.checkNotNullParam("url", url); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Create a new Builder initialized with values from an existing PushNotificationConfig. - * - * @param config the PushNotificationConfig to copy values from - * @return the builder - */ - public static Builder builder(PushNotificationConfig config) { - return new Builder(config); - } - - /** - * Builder for constructing {@link PushNotificationConfig} instances. - *

      - * Provides a fluent API for building push notification configurations with optional - * authentication and identification. - */ - public static class Builder { - private @Nullable String url; - private @Nullable String token; - private @Nullable AuthenticationInfo authentication; - private @Nullable String id; - - /** Creates an empty builder. */ - private Builder() { - } - - /** - * Creates a builder initialized from an existing configuration. - * - * @param notificationConfig the configuration to copy - */ - private Builder(PushNotificationConfig notificationConfig) { - this.url = notificationConfig.url; - this.token = notificationConfig.token; - this.authentication = notificationConfig.authentication; - this.id = notificationConfig.id; - } - - /** - * Sets the push notification endpoint URL. - * - * @param url the HTTP/HTTPS endpoint (required) - * @return this builder - */ - public Builder url(String url) { - this.url = url; - return this; - } - - /** - * Sets the bearer token for simple authentication. - * - * @param token the bearer token - * @return this builder - */ - public Builder token(String token) { - this.token = token; - return this; - } - - /** - * Sets complex authentication information. - * - * @param authenticationInfo the authentication configuration - * @return this builder - */ - public Builder authentication(AuthenticationInfo authenticationInfo) { - this.authentication = authenticationInfo; - return this; - } - - /** - * Sets the client-provided configuration identifier. - * - * @param id the configuration ID - * @return this builder - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Builds the {@link PushNotificationConfig}. - * - * @return a new push notification configuration - * @throws IllegalArgumentException if url is null - */ - public PushNotificationConfig build() { - return new PushNotificationConfig(Assert.checkNotNullParam("url", url), token, authentication, id); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java deleted file mode 100644 index c84f4d79f..000000000 --- a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * A2A Protocol error indicating that the agent does not support push notifications. - *

      - * This error is returned when a client attempts push notification operations - * on an agent that has {@link AgentCapabilities#pushNotifications()} set to {@code false}. - *

      - * Push notifications allow agents to proactively send task updates to clients via - * HTTP callbacks. Agents that don't support this capability will return this error - * for all push notification-related methods. - *

      - * Corresponds to A2A-specific error code {@code -32003}. - *

      - * Usage example: - *

      {@code
      - * if (!agentCard.capabilities().pushNotifications()) {
      - *     throw new PushNotificationNotSupportedError();
      - * }
      - * }
      - * - * @see AgentCapabilities#pushNotifications() for push notification capability - * @see TaskPushNotificationConfig for push notification configuration - * @see A2A Protocol Specification - */ -public class PushNotificationNotSupportedError extends A2AProtocolError { - - /** - * Constructs error with default message. - */ - public PushNotificationNotSupportedError() { - this(null, null, null); - } - - /** - * Constructs error with all parameters. - * - * @param code the error code (defaults to -32003 if null) - * @param message the error message (defaults to "Push Notification is not supported" if null) - * @param data additional error data (optional) - */ - public PushNotificationNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE), - defaultIfNull(message, "Push Notification is not supported"), - data, - "https://a2a-protocol.org/errors/push-notification-not-supported"); - } -} diff --git a/spec/src/main/java/io/a2a/spec/SecurityRequirement.java b/spec/src/main/java/io/a2a/spec/SecurityRequirement.java deleted file mode 100644 index 1a3729369..000000000 --- a/spec/src/main/java/io/a2a/spec/SecurityRequirement.java +++ /dev/null @@ -1,110 +0,0 @@ -package io.a2a.spec; - -import static java.util.Collections.unmodifiableMap; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import io.a2a.util.Assert; - -/** - * Represents a security requirement in the A2A Protocol. - *

      - * A SecurityRequirement defines which security schemes must be satisfied to access an agent or skill. - * It maps security scheme names to lists of required scopes. When multiple scheme entries are present - * in a single SecurityRequirement, ALL must be satisfied (AND relationship). When multiple - * SecurityRequirements are present in a list, any ONE may be satisfied (OR relationship). - *

      - * This class corresponds to the {@code SecurityRequirement} type in the A2A Protocol specification, - * which contains a {@code schemes} field mapping scheme names to scope arrays. - *

      - * Example usage: - *

      {@code
      - * // Single OAuth2 requirement with specific scopes
      - * SecurityRequirement oauth2Req = SecurityRequirement.builder()
      - *     .scheme("oauth2", List.of("read", "write"))
      - *     .build();
      - *
      - * // API key requirement with no scopes
      - * SecurityRequirement apiKeyReq = SecurityRequirement.builder()
      - *     .scheme("apiKey", List.of())
      - *     .build();
      - *
      - * // Combined requirement: both OAuth2 AND API key required
      - * SecurityRequirement combinedReq = SecurityRequirement.builder()
      - *     .scheme("oauth2", List.of("profile"))
      - *     .scheme("apiKey", List.of())
      - *     .build();
      - * }
      - * - * @param schemes map of security scheme names to lists of required scopes - * @see SecurityScheme - * @see AgentCard#securityRequirements() - * @see AgentSkill#securityRequirements() - * @see A2A Protocol Specification - */ -public record SecurityRequirement(Map> schemes) { - - /** - * Creates a SecurityRequirement with the specified schemes map. - * - * @param schemes map of security scheme names to lists of required scopes - */ - public SecurityRequirement { - Assert.checkNotNullParam("schemes", schemes); - schemes = unmodifiableMap(new LinkedHashMap<>(schemes)); - } - - /** - * Creates a new Builder for constructing SecurityRequirement instances. - * - * @return a new builder instance - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing immutable {@link SecurityRequirement} instances. - *

      - * Example usage: - *

      {@code
      -     * SecurityRequirement requirement = SecurityRequirement.builder()
      -     *     .scheme("oauth2", List.of("read", "write"))
      -     *     .scheme("apiKey", List.of())
      -     *     .build();
      -     * }
      - */ - public static class Builder { - - private final Map> schemes = new LinkedHashMap<>(); - - /** - * Creates a new Builder with an empty schemes map. - */ - private Builder() { - } - - /** - * Adds a security scheme with its required scopes. - * - * @param schemeName the name of the security scheme (must match a key in securitySchemes) - * @param scopes the list of required scopes for this scheme (empty list for no specific scopes) - * @return this builder for method chaining - */ - public Builder scheme(String schemeName, List scopes) { - this.schemes.put(schemeName, List.copyOf(scopes)); - return this; - } - - /** - * Builds an immutable {@link SecurityRequirement} from the current builder state. - * - * @return a new SecurityRequirement instance - */ - public SecurityRequirement build() { - return new SecurityRequirement(schemes); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/SecurityScheme.java b/spec/src/main/java/io/a2a/spec/SecurityScheme.java deleted file mode 100644 index 0fad71ed7..000000000 --- a/spec/src/main/java/io/a2a/spec/SecurityScheme.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.a2a.spec; - -/** - * Base interface for security schemes used to authenticate access to agent endpoints. - *

      - * This sealed interface defines a discriminated union of authentication mechanisms based on - * the OpenAPI 3.0 Security Scheme Object specification. Each implementation represents a - * different authentication strategy that can be declared in an {@link AgentCard}. - *

      - * Supported security schemes: - *

        - *
      • {@link APIKeySecurityScheme} - API key in header, query, or cookie
      • - *
      • {@link HTTPAuthSecurityScheme} - HTTP Basic or Bearer authentication
      • - *
      • {@link OAuth2SecurityScheme} - OAuth 2.0 flows
      • - *
      • {@link OpenIdConnectSecurityScheme} - OpenID Connect discovery
      • - *
      • {@link MutualTLSSecurityScheme} - Client certificate authentication
      • - *
      - * - * @see AgentCard#securitySchemes() for security scheme declarations - * @see OpenAPI Security Scheme Object - * @see A2A Protocol Specification - */ -public sealed interface SecurityScheme permits APIKeySecurityScheme, HTTPAuthSecurityScheme, OAuth2SecurityScheme, - OpenIdConnectSecurityScheme, MutualTLSSecurityScheme { - - /** - * Returns the human-readable description of this security scheme. - * @return the description, or null if not provided - */ - String description(); - - /** - * Returns the type of the security scheme. - * @return the type of the security scheme. - */ - String type(); -} diff --git a/spec/src/main/java/io/a2a/spec/StreamingEventKind.java b/spec/src/main/java/io/a2a/spec/StreamingEventKind.java deleted file mode 100644 index a8d0dd628..000000000 --- a/spec/src/main/java/io/a2a/spec/StreamingEventKind.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.a2a.spec; - -/** - * Sealed interface for events that can be emitted during streaming A2A Protocol operations. - *

      - * StreamingEventKind represents events suitable for asynchronous, progressive updates during - * agent task execution. Streaming allows agents to provide incremental feedback as work progresses, - * rather than waiting until task completion. - *

      - * Streaming events use polymorphic JSON serialization where the JSON member name itself acts as - * the type discriminator (e.g., "task", "message", "statusUpdate", "artifactUpdate"). - * This aligns with Protocol Buffers' oneof semantics and modern API design practices. - *

      - * Permitted implementations: - *

        - *
      • {@link Task} - Complete task state (typically the final event in a stream)
      • - *
      • {@link Message} - Full message (complete message in the stream)
      • - *
      • {@link TaskStatusUpdateEvent} - Incremental status updates (e.g., SUBMITTED → WORKING → COMPLETED)
      • - *
      • {@link TaskArtifactUpdateEvent} - Incremental artifact updates (partial results, chunks)
      • - *
      - *

      - * Streaming events enable patterns like: - *

        - *
      • Progressive text generation (chunks of response as generated)
      • - *
      • Status notifications (task state transitions)
      • - *
      • Partial results (early artifacts before task completion)
      • - *
      - * - * @see Event - * @see EventKind - * @see UpdateEvent - */ -public sealed interface StreamingEventKind extends Event permits Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent { - - /** - * Returns the type identifier for this streaming event. - *

      - * This method provides programmatic type discrimination for routing, logging, and debugging. - * NOTE: This value is NOT serialized to JSON in protocol v1.0+. - * For JSON serialization, the wrapper field name serves as the discriminator. - *

      - * Use {@code instanceof} pattern matching to determine the concrete event type: - *

      {@code
      -     * if (event instanceof Task task) {
      -     *     // Handle task
      -     * } else if (event instanceof TaskStatusUpdateEvent statusUpdate) {
      -     *     // Handle status update
      -     * }
      -     * }
      - * - * @return the event type identifier (e.g., "task", "message", "statusUpdate", "artifactUpdate") - */ - String kind(); -} diff --git a/spec/src/main/java/io/a2a/spec/Task.java b/spec/src/main/java/io/a2a/spec/Task.java deleted file mode 100644 index fd7cfce01..000000000 --- a/spec/src/main/java/io/a2a/spec/Task.java +++ /dev/null @@ -1,265 +0,0 @@ -package io.a2a.spec; - -import java.util.List; -import java.util.Map; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Represents a single, stateful operation or conversation between a client and an agent in the A2A Protocol. - *

      - * A Task encapsulates the complete lifecycle of an agent interaction, from submission through completion, - * cancellation, or failure. It maintains the current state, accumulated artifacts (responses), conversation - * history, and metadata associated with the operation. - *

      - * Tasks are the fundamental unit of work in the A2A Protocol. When a client sends a message to an agent, - * a Task is created to track the operation. The agent updates the Task's state as it processes the request, - * and may add artifacts containing partial or final responses. The Task's status transitions through - * various states (SUBMITTED, WORKING, COMPLETED, etc.) until reaching a final state. - *

      - * Tasks support both blocking and streaming patterns: - *

        - *
      • Blocking: Client sends a message and waits for the Task to reach a final state
      • - *
      • Streaming: Client subscribes to Task updates and receives incremental artifacts as they are produced
      • - *
      - *

      - * Tasks are immutable once created (including their history, artifacts and metadata attributes). - * They use the Builder pattern for construction. Updates to a Task's - * state are communicated via new Task instances or TaskStatusUpdateEvent/TaskArtifactUpdateEvent objects. - *

      - * This class implements {@link EventKind} and {@link StreamingEventKind}, allowing Task instances to - * be transmitted as events in both blocking and streaming scenarios. - * - * @param id the unique identifier for this task - * @param contextId the context identifier associating this task with a conversation or session - * @param status the current status of the task - * @param artifacts the list of artifacts produced by the agent during task execution - * @param history the conversation history for this task - * @param metadata arbitrary metadata associated with the task - * @see TaskStatus - * @see TaskState - * @see Artifact - * @see Message - * @see A2A Protocol Specification - */ -public record Task(String id, String contextId, TaskStatus status, @Nullable List artifacts, - @Nullable List history, @Nullable Map metadata) implements EventKind, StreamingEventKind { - - /** - * The identifier when used in streaming responses - */ - public static final String STREAMING_EVENT_ID = "task"; - - /** - * Compact constructor with validation and defensive copying. - * - * @param id the task identifier - * @param contextId the context identifier - * @param status the task status - * @param artifacts the list of artifacts produced by the task - * @param history the message history for this task - * @param metadata additional metadata for the task - * @throws IllegalArgumentException if id, contextId, or status is null - */ - public Task { - Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("contextId", contextId); - Assert.checkNotNullParam("status", status); - artifacts = artifacts != null ? List.copyOf(artifacts) : List.of(); - history = history != null ? List.copyOf(history) : List.of(); - metadata = (metadata != null) ? Map.copyOf(metadata) : null; - } - - @Override - public String kind() { - return STREAMING_EVENT_ID; - } - - /** - * Creates a new Builder for constructing Task instances. - * - * @return a new Task.Builder instance - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Creates a new Builder initialized with values from an existing Task. - *

      - * This constructor allows for creating a modified copy of an existing Task - * by copying all fields and then selectively updating specific values. - * - * @param task the Task to copy values from - * @return a new Builder instance initialized with the task's values - */ - public static Builder builder(Task task) { - return new Builder(task); - } - - /** - * Builder for constructing immutable {@link Task} instances. - *

      - * The Builder pattern is used to enforce immutability of Task objects while providing - * a fluent API for setting required and optional fields. This approach ensures that once - * a Task is created, its state cannot be modified directly, which is important for - * thread-safety and protocol correctness. - *

      - * Example usage: - *

      {@code
      -     * Task task = Task.builder()
      -     *     .id("task-123")
      -     *     .contextId("context-456")
      -     *     .status(new TaskStatus(TaskState.WORKING))
      -     *     .artifacts(List.of(new Artifact(...)))
      -     *     .history(List.of(userMessage))
      -     *     .metadata(Map.of("key", "value"))
      -     *     .build();
      -     * }
      - */ - public static class Builder { - private @Nullable String id; - private @Nullable String contextId; - private @Nullable TaskStatus status; - private @Nullable List artifacts; - private @Nullable List history; - private @Nullable Map metadata; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Creates a new Builder initialized with values from an existing Task. - * - * @param task the Task to copy values from - */ - private Builder(Task task) { - id = task.id(); - contextId = task.contextId(); - status = task.status(); - artifacts = task.artifacts(); - history = task.history(); - metadata = task.metadata(); - - } - - /** - * Sets the unique identifier for this task. - * - * @param id the task ID (required) - * @return this builder for method chaining - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Sets the context identifier associating this task with a conversation or session. - *

      - * Multiple tasks may share the same contextId if they are part of a multi-turn - * conversation or related workflow. - * - * @param contextId the context ID (required) - * @return this builder for method chaining - */ - public Builder contextId(String contextId) { - this.contextId = contextId; - return this; - } - - /** - * Sets the current status of the task. - *

      - * The status includes the state (SUBMITTED, WORKING, COMPLETED, etc.), - * an optional message, and a timestamp. - * - * @param status the task status (required) - * @return this builder for method chaining - * @see TaskStatus - */ - public Builder status(TaskStatus status) { - this.status = status; - return this; - } - - /** - * Sets the list of artifacts produced by the agent during task execution. - *

      - * Artifacts represent the agent's responses or output, which may include - * text, files, data, or other content types. Artifacts accumulate over the - * lifetime of the task, especially in streaming scenarios. - * - * @param artifacts the list of artifacts (optional) - * @return this builder for method chaining - * @see Artifact - */ - public Builder artifacts(@Nullable List artifacts) { - this.artifacts = artifacts; - return this; - } - - /** - * Sets the conversation history for this task. - *

      - * The history contains all messages exchanged between the client and agent - * as part of this task, providing context for multi-turn interactions. - * - * @param history the list of messages (optional) - * @return this builder for method chaining - * @see Message - */ - public Builder history(@Nullable List history) { - this.history = history; - return this; - } - - /** - * Sets the conversation history using a varargs array of messages. - *

      - * This is a convenience method for setting history without creating a List explicitly. - * - * @param history the messages to include in the history - * @return this builder for method chaining - * @see Message - */ - public Builder history(Message... history) { - this.history = List.of(history); - return this; - } - - /** - * Sets arbitrary metadata associated with the task. - *

      - * Metadata can be used to store custom information about the task, - * such as client identifiers, routing information, or application-specific data. - * - * @param metadata map of metadata key-value pairs (optional) - * @return this builder for method chaining - */ - public Builder metadata(Map metadata) { - this.metadata = metadata; - return this; - } - - /** - * Builds an immutable {@link Task} from the current builder state. - * - * @return a new Task instance - * @throws IllegalArgumentException if any required field (id, contextId, status) is null - */ - public Task build() { - return new Task( - Assert.checkNotNullParam("id", id), - Assert.checkNotNullParam("contextId", contextId), - Assert.checkNotNullParam("status", status), - artifacts, - history, - metadata); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java deleted file mode 100644 index 1d009673d..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java +++ /dev/null @@ -1,223 +0,0 @@ -package io.a2a.spec; - -import java.util.Map; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Event notifying that a task artifact has been created, modified, or appended to. - *

      - * TaskArtifactUpdateEvent is emitted during streaming operations to deliver partial or complete - * artifacts as they become available. This enables progressive result delivery and real-time - * feedback for long-running operations. - *

      - * The event supports two primary patterns: - *

        - *
      • Complete artifacts - New artifacts added to the task (append=false or null)
      • - *
      • Incremental chunks - Content appended to existing artifacts (append=true)
      • - *
      - *

      - * Use cases include: - *

        - *
      • Streaming text generation (progressive LLM responses)
      • - *
      • Incremental file generation (large documents built over time)
      • - *
      • Partial results (early outputs before complete analysis)
      • - *
      - *

      - * The {@code lastChunk} flag indicates whether this is the final update for an artifact, - * allowing clients to distinguish between intermediate and final states. - * - * @param taskId the task identifier (required) - * @param artifact the artifact being updated (required) - * @param contextId the context identifier (required) - * @param append whether to append to existing artifact (optional) - * @param lastChunk whether this is the final chunk (optional) - * @param metadata additional metadata (optional) - * @see UpdateEvent - * @see StreamingEventKind - * @see Artifact - * @see Task - */ -public record TaskArtifactUpdateEvent(String taskId, Artifact artifact, String contextId, @Nullable Boolean append, - @Nullable Boolean lastChunk, @Nullable Map metadata) implements EventKind, StreamingEventKind, UpdateEvent { - - /** - * The identifier when used in streaming responses - */ - public static final String STREAMING_EVENT_ID = "artifactUpdate"; - - /** - * Compact constructor with validation. - * - * @param taskId the task identifier (required) - * @param artifact the artifact being updated (required) - * @param contextId the context identifier (required) - * @param append whether to append to existing artifact (optional) - * @param lastChunk whether this is the final chunk (optional) - * @param metadata additional metadata (optional) - * @throws IllegalArgumentException if taskId, artifact, or contextId is null - */ - public TaskArtifactUpdateEvent { - Assert.checkNotNullParam("taskId", taskId); - Assert.checkNotNullParam("artifact", artifact); - Assert.checkNotNullParam("contextId", contextId); - } - - @Override - public String kind() { - return STREAMING_EVENT_ID; - } - - /** - * Creates a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Creates a new Builder initialized with values from an existing TaskArtifactUpdateEvent. - * - * @param event the TaskArtifactUpdateEvent to copy values from - * @return the builder - */ - public static Builder builder(TaskArtifactUpdateEvent event) { - return new Builder(event); - } - - /** - * Builder for constructing {@link TaskArtifactUpdateEvent} instances. - *

      - * Example for complete artifact: - *

      {@code
      -     * TaskArtifactUpdateEvent event = TaskArtifactUpdateEvent.builder()
      -     *     .taskId("task-123")
      -     *     .contextId("ctx-456")
      -     *     .artifact(new Artifact.Builder()
      -     *         .artifactId("artifact-789")
      -     *         .parts(List.of(new TextPart("Analysis complete")))
      -     *         .build())
      -     *     .build();
      -     * }
      - *

      - * Example for incremental chunk: - *

      {@code
      -     * TaskArtifactUpdateEvent chunk = TaskArtifactUpdateEvent.builder()
      -     *     .taskId("task-123")
      -     *     .contextId("ctx-456")
      -     *     .artifact(new Artifact.Builder()
      -     *         .artifactId("artifact-789")
      -     *         .parts(List.of(new TextPart("more text...")))
      -     *         .build())
      -     *     .append(true)
      -     *     .lastChunk(false)
      -     *     .build();
      -     * }
      - */ - public static class Builder { - - private @Nullable String taskId; - private @Nullable Artifact artifact; - private @Nullable String contextId; - private @Nullable Boolean append; - private @Nullable Boolean lastChunk; - private @Nullable Map metadata; - - private Builder() { - } - - private Builder(TaskArtifactUpdateEvent existingTaskArtifactUpdateEvent) { - this.taskId = existingTaskArtifactUpdateEvent.taskId; - this.artifact = existingTaskArtifactUpdateEvent.artifact; - this.contextId = existingTaskArtifactUpdateEvent.contextId; - this.append = existingTaskArtifactUpdateEvent.append; - this.lastChunk = existingTaskArtifactUpdateEvent.lastChunk; - this.metadata = existingTaskArtifactUpdateEvent.metadata; - } - - /** - * Sets the task identifier. - * - * @param taskId the task ID (required) - * @return this builder for method chaining - */ - public Builder taskId(String taskId) { - this.taskId = taskId; - return this; - } - - /** - * Sets the artifact being updated. - * - * @param artifact the artifact (required) - * @return this builder for method chaining - */ - public Builder artifact(Artifact artifact) { - this.artifact = artifact; - return this; - } - - /** - * Sets the context identifier. - * - * @param contextId the context ID (required) - * @return this builder for method chaining - */ - public Builder contextId(String contextId) { - this.contextId = contextId; - return this; - } - - /** - * Sets whether this update should append to an existing artifact. - * - * @param append true to append, false or null for new artifact - * @return this builder for method chaining - */ - public Builder append(@Nullable Boolean append) { - this.append = append; - return this; - } - - /** - * Sets whether this is the final chunk for the artifact. - * - * @param lastChunk true if final chunk, false or null otherwise - * @return this builder for method chaining - */ - public Builder lastChunk(@Nullable Boolean lastChunk) { - this.lastChunk = lastChunk; - return this; - } - - /** - * Sets the metadata for this event. - * - * @param metadata map of metadata key-value pairs (optional) - * @return this builder for method chaining - */ - public Builder metadata(Map metadata) { - this.metadata = metadata; - return this; - } - - /** - * Builds the TaskArtifactUpdateEvent. - * - * @return a new TaskArtifactUpdateEvent instance - * @throws IllegalArgumentException if required fields are missing - */ - public TaskArtifactUpdateEvent build() { - return new TaskArtifactUpdateEvent( - Assert.checkNotNullParam("taskId", taskId), - Assert.checkNotNullParam("artifact", artifact), - Assert.checkNotNullParam("contextId", contextId), - append, - lastChunk, - metadata); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskIdParams.java b/spec/src/main/java/io/a2a/spec/TaskIdParams.java deleted file mode 100644 index 972bb4a22..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskIdParams.java +++ /dev/null @@ -1,97 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -/** - * Parameters containing a task identifier for task-related operations. - *

      - * This simple parameter record is used by operations that only need a task ID, - * and similar task-specific requests. It optionally includes metadata for additional context. - * - * @param id the unique task identifier (required) - * @param tenant optional tenant, provided as a path parameter. - * @see A2A Protocol Specification - */ -public record TaskIdParams(String id, String tenant) { - - /** - * Compact constructor for validation. - * Validates that required parameters are not null. - * - * @param id the task identifier - * @param tenant the tenant identifier - */ - public TaskIdParams { - Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("tenant", tenant); - } - - /** - * Convenience constructor with default tenant. - * - * @param id the task identifier (required) - */ - public TaskIdParams(String id) { - this(id, ""); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private @Nullable String id; - private @Nullable String tenant; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the id. - * - * @param id the task identifier (required) - * @return this builder for method chaining - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Sets the tenant. - * - * @param tenant the tenant identifier - * @return this builder for method chaining - */ - public Builder tenant(String tenant) { - this.tenant = tenant; - return this; - } - - /** - * Builds the TaskIdParams. - * - * @return a new TaskIdParams instance - * @throws IllegalArgumentException if id is null - */ - public TaskIdParams build() { - return new TaskIdParams( - Assert.checkNotNullParam("id", id), - Utils.defaultIfNull(tenant,"") - ); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java deleted file mode 100644 index 83e19ec54..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * A2A Protocol error indicating that a task cannot be canceled in its current state. - *

      - * This error is returned when a client attempts to cancel a task - * but the task is in a terminal state ({@link TaskState#TASK_STATE_COMPLETED}, {@link TaskState#TASK_STATE_FAILED}, - * {@link TaskState#TASK_STATE_CANCELED}) where cancellation is not applicable. - *

      - * Tasks can only be canceled when they are in non-terminal states such as {@link TaskState#TASK_STATE_SUBMITTED} - * or {@link TaskState#TASK_STATE_WORKING}. - *

      - * Corresponds to A2A-specific error code {@code -32002}. - *

      - * Usage example: - *

      {@code
      - * Task task = taskStore.getTask(taskId);
      - * if (task.status().state().isFinal()) {
      - *     throw new TaskNotCancelableError(
      - *         "Task in " + task.status().state() + " state cannot be canceled"
      - *     );
      - * }
      - * }
      - * - * @see TaskState for task state definitions - * @see TaskStatus#state() for current task state - * @see A2A Protocol Specification - */ -public class TaskNotCancelableError extends A2AProtocolError { - - /** - * Constructs error with default message. - */ - public TaskNotCancelableError() { - this(null, null, null); - } - - /** - * Constructs error with all parameters. - * - * @param code the error code (defaults to -32002 if null) - * @param message the error message (defaults to "Task cannot be canceled" if null) - * @param data additional error data (optional) - */ - public TaskNotCancelableError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, TASK_NOT_CANCELABLE_ERROR_CODE), - defaultIfNull(message, "Task cannot be canceled"), - data, - "https://a2a-protocol.org/errors/task-not-cancelable"); - } - - /** - * Constructs error with custom message. - * - * @param message the error message - */ - public TaskNotCancelableError(String message) { - this(null, message, null); - } - -} diff --git a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java deleted file mode 100644 index 8bb8eea27..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java +++ /dev/null @@ -1,58 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * A2A Protocol error indicating that the requested task ID does not exist. - *

      - * This error is returned when a client attempts to perform operations on a task using - * a task ID that is not found in the server's task store. - *

      - * Common causes: - *

        - *
      • Task ID was never created
      • - *
      • Task has been removed from the task store (expired or deleted)
      • - *
      • Task ID typo or incorrect value
      • - *
      • Task belongs to a different agent or server instance
      • - *
      - *

      - * Corresponds to A2A-specific error code {@code -32001}. - *

      - * Usage example: - *

      {@code
      - * Task task = taskStore.getTask(taskId);
      - * if (task == null) {
      - *     throw new TaskNotFoundError();
      - * }
      - * }
      - * - * @see Task for task object definition - * @see A2A Protocol Specification - */ -public class TaskNotFoundError extends A2AProtocolError { - - /** - * Constructs error with default message. - */ - public TaskNotFoundError() { - this(null, null, null); - } - - /** - * Constructs error with all parameters. - * - * @param code the error code (defaults to -32001 if null) - * @param message the error message (defaults to "Task not found" if null) - * @param data additional error data (optional) - */ - public TaskNotFoundError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, TASK_NOT_FOUND_ERROR_CODE), - defaultIfNull(message, "Task not found"), - data, - "https://a2a-protocol.org/errors/task-not-found"); - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java deleted file mode 100644 index 9f973e897..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * Associates a push notification configuration with a specific task. - *

      - * This record binds a {@link PushNotificationConfig} to a particular task ID, enabling - * the agent to send asynchronous updates about task progress to the configured endpoint. - * When task events occur (status changes, artifact updates), the agent will POST updates - * to the specified notification URL. - *

      - * Used for managing task-specific push notification settings via the push notification - * management methods ({@code tasks/pushNotificationConfig/set}, {@code tasks/pushNotificationConfig/get}, etc.). - * - * @param taskId the unique identifier of the task to receive push notifications for (required) - * @param config the push notification endpoint and authentication configuration (required) - * @param tenant optional tenant identifier, provided as a path parameter - * @see PushNotificationConfig for notification endpoint details - * @see A2A Protocol Specification - */ -public record TaskPushNotificationConfig(String taskId, PushNotificationConfig config, @Nullable String tenant) { - - /** - * Compact constructor for validation. - * Validates that required parameters are not null. - * - * @param taskId the task identifier - * @param config the push notification configuration - * @param tenant the tenant identifier - */ - public TaskPushNotificationConfig { - Assert.checkNotNullParam("taskId", taskId); - Assert.checkNotNullParam("config", config); - Assert.checkNotNullParam("configId", config.id()); - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java b/spec/src/main/java/io/a2a/spec/TaskQueryParams.java deleted file mode 100644 index 9f5805f98..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java +++ /dev/null @@ -1,122 +0,0 @@ -package io.a2a.spec; - -import io.a2a.util.Assert; -import io.a2a.util.Utils; -import org.jspecify.annotations.Nullable; - -/** - * Defines parameters for querying a task, with an option to limit history length. - * - * @param id the ID for the task to be queried - * @param historyLength the maximum number of items of history for the task to include in the response - * @param tenant optional tenant, provided as a path parameter. - */ -public record TaskQueryParams(String id, @Nullable Integer historyLength, String tenant) { - - /** - * Compact constructor for validation. - * Validates that required parameters are not null and historyLength is non-negative if provided. - * - * @param id the task identifier - * @param historyLength maximum number of history items - * @param tenant the tenant identifier - * @throws IllegalArgumentException if historyLength is negative - */ - public TaskQueryParams { - Assert.checkNotNullParam("id", id); - Assert.checkNotNullParam("tenant", tenant); - if (historyLength != null && historyLength < 0) { - throw new IllegalArgumentException("Invalid history length"); - } - } - - /** - * Convenience constructor with default tenant. - * - * @param id the task identifier (required) - * @param historyLength maximum number of history items to include (optional) - */ - public TaskQueryParams(String id, @Nullable Integer historyLength) { - this(id, historyLength, ""); - } - - /** - * Convenience constructor with defaults for tenant and historyLength. - * - * @param id the task identifier (required) - */ - public TaskQueryParams(String id) { - this(id, null, ""); - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for constructing instances. - */ - public static class Builder { - private @Nullable String id; - private @Nullable Integer historyLength; - private @Nullable String tenant; - - /** - * Creates a new Builder with all fields unset. - */ - private Builder() { - } - - /** - * Sets the id. - * - * @param id the task identifier (required) - * @return this builder for method chaining - */ - public Builder id(String id) { - this.id = id; - return this; - } - - /** - * Sets the historyLength. - * - * @param historyLength the maximum number of history items to include - * @return this builder for method chaining - */ - public Builder historyLength(Integer historyLength) { - this.historyLength = historyLength; - return this; - } - - /** - * Sets the tenant. - * - * @param tenant the tenant identifier - * @return this builder for method chaining - */ - public Builder tenant(String tenant) { - this.tenant = tenant; - return this; - } - - /** - * Builds the TaskQueryParams. - * - * @return a new TaskQueryParams instance - * @throws IllegalArgumentException if id is null or historyLength is negative - */ - public TaskQueryParams build() { - return new TaskQueryParams( - Assert.checkNotNullParam("id", id), - historyLength, - Utils.defaultIfNull(tenant,"") - ); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskState.java b/spec/src/main/java/io/a2a/spec/TaskState.java deleted file mode 100644 index ca5354167..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskState.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.a2a.spec; - -/** - * Defines the lifecycle states of a {@link Task} in the A2A Protocol. - *

      - * TaskState represents the discrete states a task can be in during its execution lifecycle. - * States are categorized as either transitional (non-final) or terminal (final), where - * terminal states indicate that the task has reached its end state and will not transition further. - *

      - * Transitional States: - *

        - *
      • TASK_STATE_SUBMITTED: Task has been received by the agent and is queued for processing
      • - *
      • TASK_STATE_WORKING: Agent is actively processing the task and may produce incremental results
      • - *
      • TASK_STATE_INPUT_REQUIRED: Agent needs additional input from the user to continue
      • - *
      • TASK_STATE_AUTH_REQUIRED: Agent requires authentication or authorization before proceeding
      • - *
      - *

      - * Terminal States: - *

        - *
      • TASK_STATE_COMPLETED: Task finished successfully with all requested work done
      • - *
      • TASK_STATE_CANCELED: Task was explicitly canceled by the user or system
      • - *
      • TASK_STATE_FAILED: Task failed due to an error during execution
      • - *
      • TASK_STATE_REJECTED: Task was rejected by the agent (e.g., invalid request, policy violation)
      • - *
      • UNRECOGNIZED: Task state cannot be determined (error recovery state)
      • - *
      - *

      - * The {@link #isFinal()} method can be used to determine if a state is terminal, which is - * important for event queue management and client polling logic. - * - * @see TaskStatus - * @see Task - * @see A2A Protocol Specification - */ -public enum TaskState { - /** Task has been received and is queued for processing (transitional state). */ - TASK_STATE_SUBMITTED(false), - - /** Agent is actively processing the task (transitional state). */ - TASK_STATE_WORKING(false), - - /** Agent requires additional input from the user to continue (transitional state). */ - TASK_STATE_INPUT_REQUIRED(false), - - /** Agent requires authentication or authorization to proceed (transitional state). */ - TASK_STATE_AUTH_REQUIRED(false), - - /** Task completed successfully (terminal state). */ - TASK_STATE_COMPLETED(true), - - /** Task was canceled by user or system (terminal state). */ - TASK_STATE_CANCELED(true), - - /** Task failed due to an error (terminal state). */ - TASK_STATE_FAILED(true), - - /** Task was rejected by the agent (terminal state). */ - TASK_STATE_REJECTED(true), - - /** Task state is unknown or cannot be determined (terminal state). */ - UNRECOGNIZED(true); - - private final boolean isFinal; - - TaskState(boolean isFinal) { - this.isFinal = isFinal; - } - - /** - * Determines whether this state is a terminal (final) state. - *

      - * Terminal states indicate that the task has completed its lifecycle and will - * not transition to any other state. This is used by the event queue system - * to determine when to close queues and by clients to know when to stop polling. - * - * @return {@code true} if this is a terminal state, {@code false} else. - */ - public boolean isFinal(){ - return isFinal; - } -} \ No newline at end of file diff --git a/spec/src/main/java/io/a2a/spec/TaskStatus.java b/spec/src/main/java/io/a2a/spec/TaskStatus.java deleted file mode 100644 index 95e70da0d..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskStatus.java +++ /dev/null @@ -1,76 +0,0 @@ -package io.a2a.spec; - -import java.time.OffsetDateTime; - -import io.a2a.util.Assert; -import java.time.ZoneOffset; -import org.jspecify.annotations.Nullable; - -/** - * Represents the status of a task at a specific point in time in the A2A Protocol. - *

      - * TaskStatus encapsulates the current state of a task along with an optional message - * providing additional context and a timestamp indicating when the status was created. - * This information is essential for tracking task lifecycle and communicating progress - * to clients. - *

      - * The status transitions through various states as the agent processes the task: - *

        - *
      • SUBMITTED: Task has been received and queued
      • - *
      • WORKING: Agent is actively processing the task
      • - *
      • INPUT_REQUIRED: Agent needs additional input from the user
      • - *
      • AUTH_REQUIRED: Agent requires authentication or authorization
      • - *
      • COMPLETED: Task finished successfully (final state)
      • - *
      • CANCELED: Task was canceled by the user or system (final state)
      • - *
      • FAILED: Task failed due to an error (final state)
      • - *
      • REJECTED: Task was rejected by the agent (final state)
      • - *
      • UNKNOWN: Task state cannot be determined (final state)
      • - *
      - *

      - * TaskStatus is immutable and automatically generates a UTC timestamp if none is provided. - * This class is used within {@link Task} objects and {@link TaskStatusUpdateEvent} instances - * to communicate state changes. - * - * @param state the current state of the task (required) - * @param message an optional message providing additional context about the status (optional) - * @param timestamp the time when this status was created, in UTC (defaults to current time if not provided) - * @see TaskState - * @see Task - * @see A2A Protocol Specification - */ -public record TaskStatus(TaskState state, @Nullable Message message, OffsetDateTime timestamp) { - - /** - * Compact constructor for validation and timestamp initialization. - * Validates that the state is not null and sets the timestamp to current UTC time if not provided. - * - * @param state the task state - * @param message optional status message - * @param timestamp the status timestamp - */ - public TaskStatus(TaskState state, @Nullable Message message, @Nullable OffsetDateTime timestamp){ - this.state = Assert.checkNotNullParam("state", state); - this.timestamp = timestamp == null ? OffsetDateTime.now(ZoneOffset.UTC) : timestamp; - this.message = message; - } - - /** - * Returns the timestamp when this status was created. - * - * @return the UTC timestamp of the status - */ - public OffsetDateTime timestamp() { - return timestamp; - } - /** - * Creates a TaskStatus with only a state, using the current UTC time as the timestamp. - *

      - * This is a convenience constructor for creating status updates without - * an accompanying message. - * - * @param state the task state (required) - */ - public TaskStatus(TaskState state) { - this(state, null, OffsetDateTime.now(ZoneOffset.UTC)); - } -} diff --git a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java deleted file mode 100644 index bacf9afc6..000000000 --- a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java +++ /dev/null @@ -1,162 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.TaskState.TASK_STATE_CANCELED; -import static io.a2a.spec.TaskState.TASK_STATE_COMPLETED; -import static io.a2a.spec.TaskState.TASK_STATE_FAILED; -import static io.a2a.spec.TaskState.TASK_STATE_INPUT_REQUIRED; -import static io.a2a.spec.TaskState.TASK_STATE_REJECTED; - -import java.util.Map; - -import com.google.gson.annotations.SerializedName; -import io.a2a.util.Assert; -import org.jspecify.annotations.Nullable; - -/** - * An event sent by the agent to notify the client of a change in a task's status. - * This is typically used in streaming or subscription models. - * - * @param taskId the task identifier (required) - * @param status the task status (required) - * @param contextId the context identifier (required) - * @param isFinal whether this is a final status - * @param metadata additional metadata (optional) - */ -public record TaskStatusUpdateEvent(String taskId, TaskStatus status, String contextId, - @SerializedName("final") boolean isFinal, @Nullable Map metadata) implements EventKind, StreamingEventKind, UpdateEvent { - - /** - * The identifier when used in streaming responses - */ - public static final String STREAMING_EVENT_ID = "statusUpdate"; - - /** - * Compact constructor with validation. - * - * @param taskId the task identifier (required) - * @param status the task status (required) - * @param contextId the context identifier (required) - * @param isFinal whether this is a final status - * @param metadata additional metadata (optional) - * @throws IllegalArgumentException if taskId, status, or contextId is null - */ - public TaskStatusUpdateEvent { - Assert.checkNotNullParam("taskId", taskId); - Assert.checkNotNullParam("status", status); - Assert.checkNotNullParam("contextId", contextId); - if (isFinal != status.state().isFinal()) { - throw new IllegalArgumentException("isFinal must be the same as the Status state"); - } - } - - @Override - public String kind() { - return STREAMING_EVENT_ID; - } - - /** - * Indicates if the task is fianl or waiting for some inputs from the client. - * @return true if the task is fianl or waiting for some inputs from the client - false otherwise. - */ - public boolean isFinalOrInterrupted() { - return status.state() == TASK_STATE_COMPLETED || status.state() == TASK_STATE_FAILED || status.state() == TASK_STATE_CANCELED || status.state() == TASK_STATE_REJECTED || status.state() == TASK_STATE_INPUT_REQUIRED; - } - - /** - * Create a new Builder - * - * @return the builder - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Create a new Builder initialized with values from an existing TaskStatusUpdateEvent. - * - * @param event the TaskStatusUpdateEvent to copy values from - * @return the builder - */ - public static Builder builder(TaskStatusUpdateEvent event) { - return new Builder(event); - } - - /** - * Builder for constructing {@link TaskStatusUpdateEvent} instances. - */ - public static class Builder { - - private @Nullable String taskId; - private @Nullable TaskStatus status; - private @Nullable String contextId; - private @Nullable Map metadata; - - private Builder() { - } - - private Builder(TaskStatusUpdateEvent existingTaskStatusUpdateEvent) { - this.taskId = existingTaskStatusUpdateEvent.taskId; - this.status = existingTaskStatusUpdateEvent.status; - this.contextId = existingTaskStatusUpdateEvent.contextId; - this.metadata = existingTaskStatusUpdateEvent.metadata; - } - - /** - * Sets the task identifier. - * - * @param id the task ID - * @return this builder for method chaining - */ - public Builder taskId(String id) { - this.taskId = id; - return this; - } - - /** - * Sets the task status. - * - * @param status the task status - * @return this builder for method chaining - */ - public Builder status(TaskStatus status) { - this.status = status; - return this; - } - - /** - * Sets the context identifier. - * - * @param contextId the context ID - * @return this builder for method chaining - */ - public Builder contextId(String contextId) { - this.contextId = contextId; - return this; - } - - /** - * Sets the metadata. - * - * @param metadata the metadata map - * @return this builder for method chaining - */ - public Builder metadata(Map metadata) { - this.metadata = metadata; - return this; - } - - /** - * Builds the TaskStatusUpdateEvent. - * - * @return a new TaskStatusUpdateEvent instance - */ - public TaskStatusUpdateEvent build() { - return new TaskStatusUpdateEvent( - Assert.checkNotNullParam("taskId", taskId), - Assert.checkNotNullParam("status", status), - Assert.checkNotNullParam("contextId", contextId), - Assert.checkNotNullParam("status", status).state().isFinal(), - metadata); - } - } -} diff --git a/spec/src/main/java/io/a2a/spec/TextPart.java b/spec/src/main/java/io/a2a/spec/TextPart.java deleted file mode 100644 index e76cdd19d..000000000 --- a/spec/src/main/java/io/a2a/spec/TextPart.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.a2a.spec; - - -import io.a2a.util.Assert; -import java.util.Map; -import org.jspecify.annotations.Nullable; - - -/** - * Represents a plain text content part within a {@link Message} or {@link Artifact}. - *

      - * TextPart is the most common part type, containing textual content such as user messages, - * agent responses, descriptions, or any other human-readable text. - *

      - * The text content is required and must be non-null. Optional metadata can provide additional - * context about the text (such as language, encoding, or formatting hints). - *

      - * Example usage: - *

      {@code
      - * TextPart greeting = new TextPart("Hello, how can I help you?");
      - * TextPart withMetadata = new TextPart("Bonjour!", Map.of("language", "fr"));
      - * }
      - * - * @param text the text content (required, must not be null) - * @param metadata additional metadata for the part - * @see Part - * @see Message - * @see Artifact - */ -public record TextPart(String text, @Nullable Map metadata) implements Part { - - /** - * The JSON member name discriminator for text parts: "text". - *

      - * In protocol v1.0+, this constant defines the JSON member name used for serialization: - * {@code { "text": "Hello, world!" }} - */ - public static final String TEXT = "text"; - - /** - * Compact constructor with validation. - * - * @param text the text content (required, must not be null) - * @throws IllegalArgumentException if text is null - */ - public TextPart (String text, @Nullable Map metadata) { - Assert.checkNotNullParam("text", text); - this.metadata = metadata == null ? null : Map.copyOf(metadata); - this.text = text; - } - - /** - * Constructor. - * - * @param text the text content (required, must not be null) - * @throws IllegalArgumentException if data is null - */ - public TextPart (String text){ - this(text, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/TransportProtocol.java b/spec/src/main/java/io/a2a/spec/TransportProtocol.java deleted file mode 100644 index 4c852903b..000000000 --- a/spec/src/main/java/io/a2a/spec/TransportProtocol.java +++ /dev/null @@ -1,90 +0,0 @@ -package io.a2a.spec; - -/** - * Enumeration of supported transport protocols for A2A Protocol communication. - *

      - * This enum defines the communication mechanisms that A2A agents and clients can use - * to exchange messages. Each transport protocol has different characteristics, advantages, - * and use cases. - *

      - * Supported transport protocols: - *

        - *
      • {@link #JSONRPC} - JSON-RPC 2.0 over HTTP (most common, human-readable)
      • - *
      • {@link #GRPC} - gRPC binary protocol (high performance, streaming)
      • - *
      • {@link #HTTP_JSON} - RESTful HTTP with JSON (REST-style endpoints)
      • - *
      - *

      - * Usage example: - *

      {@code
      - * TransportProtocol protocol = TransportProtocol.JSONRPC;
      - * String protocolName = protocol.asString();  // "JSONRPC"
      - * TransportProtocol parsed = TransportProtocol.fromString("JSONRPC");
      - * }
      - * - * @see JSON-RPC 2.0 Specification - * @see gRPC - * @see A2A Protocol Specification - */ -public enum TransportProtocol { - /** - * JSON-RPC 2.0 transport protocol over HTTP. - *

      - * This is the primary and most widely supported transport for the A2A Protocol. - * It uses JSON-RPC 2.0 request/response semantics with JSON encoding, making it - * human-readable and easy to debug. Supports both synchronous and streaming communication. - */ - JSONRPC("JSONRPC"), - - /** - * gRPC binary transport protocol. - *

      - * High-performance binary protocol using Protocol Buffers for serialization. - * Provides efficient streaming, strong typing, and cross-language support. - * Suitable for high-throughput scenarios and service-to-service communication. - */ - GRPC("GRPC"), - - /** - * HTTP+JSON RESTful transport protocol. - *

      - * REST-style HTTP endpoints with JSON payloads. Provides a more traditional - * web API approach compared to JSON-RPC, using HTTP methods (GET, POST, etc.) - * and resource-oriented URLs. - */ - HTTP_JSON("HTTP+JSON"); - - private final String transport; - - TransportProtocol(String transport) { - this.transport = transport; - } - - /** - * Returns the string representation of this transport protocol. - *

      - * Used for JSON serialization. - * - * @return the transport protocol name as a string - */ - public String asString() { - return transport; - } - - /** - * Parses a string into a {@link TransportProtocol} enum constant. - *

      - * Used for JSON deserialization. - * - * @param transport the transport protocol string (e.g., "JSONRPC", "GRPC", "HTTP+JSON") - * @return the corresponding TransportProtocol enum constant - * @throws IllegalArgumentException if the transport string is not recognized - */ - public static TransportProtocol fromString(String transport) { - return switch (transport) { - case "JSONRPC" -> JSONRPC; - case "GRPC" -> GRPC; - case "HTTP+JSON" -> HTTP_JSON; - default -> throw new IllegalArgumentException("Invalid transport: " + transport); - }; - } -} diff --git a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java deleted file mode 100644 index 65bdbed9a..000000000 --- a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - -/** - * A2A Protocol error indicating that the requested operation is not supported by the agent. - *

      - * This error is returned when a client attempts an operation that is valid according to the - * A2A Protocol but not implemented or enabled by the specific agent. This is distinct from - * {@link MethodNotFoundError}, which indicates an unknown JSON-RPC method. - *

      - * Common scenarios: - *

        - *
      • Calling streaming methods when {@link AgentCapabilities#streaming()} is false
      • - *
      • Attempting push notification operations when {@link AgentCapabilities#pushNotifications()} is false
      • - *
      • Using optional protocol features not implemented by the agent
      • - *
      • Agent-specific operations disabled by configuration
      • - *
      - *

      - * Corresponds to A2A-specific error code {@code -32004}. - *

      - * Usage example: - *

      {@code
      - * if (!agentCard.capabilities().streaming()) {
      - *     throw new UnsupportedOperationError();
      - * }
      - * }
      - * - * @see AgentCapabilities for agent capability declarations - * @see MethodNotFoundError for unknown method errors - * @see A2A Protocol Specification - */ -public class UnsupportedOperationError extends A2AProtocolError { - - /** - * Constructs error with all parameters. - * - * @param code the error code (defaults to -32004 if null) - * @param message the error message (defaults to "This operation is not supported" if null) - * @param data additional error data (optional) - */ - public UnsupportedOperationError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, UNSUPPORTED_OPERATION_ERROR_CODE), - defaultIfNull(message, "This operation is not supported"), - data, - "https://a2a-protocol.org/errors/unsupported-operation"); - } - - /** - * Constructs error with default message. - */ - public UnsupportedOperationError() { - this(null, null, null); - } -} diff --git a/spec/src/main/java/io/a2a/spec/UpdateEvent.java b/spec/src/main/java/io/a2a/spec/UpdateEvent.java deleted file mode 100644 index 996977498..000000000 --- a/spec/src/main/java/io/a2a/spec/UpdateEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.a2a.spec; - -/** - * Sealed interface for incremental update events during task execution. - *

      - * UpdateEvent represents partial updates to task state or content that can be emitted during - * streaming operations. These events enable real-time progress tracking and incremental result - * delivery without waiting for complete task finalization. - *

      - * Permitted implementations: - *

        - *
      • {@link TaskStatusUpdateEvent} - Updates to task status and state transitions
      • - *
      • {@link TaskArtifactUpdateEvent} - Updates to task artifacts (creation, modification, appending)
      • - *
      - *

      - * Update events are always part of {@link StreamingEventKind} and provide granular visibility - * into agent progress during long-running operations. - * - * @see StreamingEventKind - * @see TaskStatusUpdateEvent - * @see TaskArtifactUpdateEvent - */ -public sealed interface UpdateEvent permits TaskStatusUpdateEvent, TaskArtifactUpdateEvent { -} diff --git a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java b/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java deleted file mode 100644 index f4caf5e77..000000000 --- a/spec/src/main/java/io/a2a/spec/VersionNotSupportedError.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.a2a.spec; - -import static io.a2a.spec.A2AErrorCodes.VERSION_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.util.Utils.defaultIfNull; - -import org.jspecify.annotations.Nullable; - - -/** - * A2A Protocol error indicating that the A2A protocol version specified in the request - * is not supported by the agent. - *

      - * This error is returned when a client specifies a protocol version (via the A2A-Version - * service parameter) that the agent does not support. Agents should return this error - * when they cannot handle the requested protocol version. - *

      - * Corresponds to A2A-specific error code {@code -32009}. - *

      - * Usage example: - *

      {@code
      - * // In agent implementation
      - * if (!isSupportedVersion(requestedVersion)) {
      - *     throw new VersionNotSupportedError(null,
      - *         "Protocol version " + requestedVersion + " is not supported", null);
      - * }
      - * }
      - * - * @see AgentInterface#protocolVersion() for supported version declaration - * @see A2A Protocol Specification - */ -public class VersionNotSupportedError extends A2AProtocolError { - - /** - * Constructs an error when the requested protocol version is not supported. - * - * @param code the error code (defaults to -32009 if null) - * @param message the error message (defaults to standard message if null) - * @param data additional error data (optional) - */ - public VersionNotSupportedError(@Nullable Integer code, @Nullable String message, @Nullable Object data) { - super( - defaultIfNull(code, VERSION_NOT_SUPPORTED_ERROR_CODE), - defaultIfNull(message, "Protocol version not supported"), - data, - "https://a2a-protocol.org/errors/version-not-supported"); - } -} diff --git a/spec/src/main/java/io/a2a/spec/package-info.java b/spec/src/main/java/io/a2a/spec/package-info.java deleted file mode 100644 index f91b3a08c..000000000 --- a/spec/src/main/java/io/a2a/spec/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * JSON processing exceptions for the A2A Java SDK. - *

      - * This package provides custom exceptions that replace Jackson's JSON processing exceptions, - * allowing the SDK to be independent of any specific JSON library implementation. - */ -@org.jspecify.annotations.NullMarked -package io.a2a.spec; diff --git a/spec/src/main/java/io/a2a/util/PageToken.java b/spec/src/main/java/io/a2a/util/PageToken.java deleted file mode 100644 index c703a903a..000000000 --- a/spec/src/main/java/io/a2a/util/PageToken.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.a2a.util; - -import java.time.Instant; - -import io.a2a.spec.InvalidParamsError; -import org.jspecify.annotations.Nullable; - -/** - * Represents a pagination token for keyset-based pagination. - *

      - * PageTokens use the format {@code "timestamp_millis:id"} where: - *

        - *
      • {@code timestamp_millis} - Unix timestamp in milliseconds (numeric)
      • - *
      • {@code id} - The entity identifier (String)
      • - *
      - * This format enables efficient keyset pagination by allowing queries to resume - * at a specific point in a timestamp-sorted, ID-secondary-sorted result set. - * - * @param timestamp The timestamp component of the page token - * @param id The identifier component of the page token - */ -public record PageToken(Instant timestamp, String id) { - - /** - * Parses a pageToken string into a PageToken record. - *

      - * Expected format: {@code "timestamp_millis:id"} - * - * @param tokenStr The pageToken string to parse, may be null or empty - * @return A PageToken instance, or null if tokenStr is null or empty - * @throws InvalidParamsError if the token format is invalid or timestamp is not numeric - */ - public static @Nullable PageToken fromString(@Nullable String tokenStr) { - if (tokenStr == null || tokenStr.isEmpty()) { - return null; - } - - String[] tokenParts = tokenStr.split(":", 2); - if (tokenParts.length != 2) { - throw new InvalidParamsError(null, - "Invalid pageToken format: expected 'timestamp:id'", null); - } - - try { - long timestampMillis = Long.parseLong(tokenParts[0]); - String id = tokenParts[1]; - if (id.isEmpty()) { - throw new InvalidParamsError(null, "Invalid pageToken format: id part cannot be empty", null); - } - return new PageToken(Instant.ofEpochMilli(timestampMillis), id); - } catch (NumberFormatException e) { - throw new InvalidParamsError(null, - "Invalid pageToken format: timestamp must be numeric milliseconds", null); - } - } - - /** - * Converts this PageToken to its string representation. - *

      - * Format: {@code "timestamp_millis:id"} - * - * @return The pageToken string - */ - @Override - public String toString() { - return timestamp.toEpochMilli() + ":" + id; - } -} diff --git a/spec/src/main/java/io/a2a/util/Utils.java b/spec/src/main/java/io/a2a/util/Utils.java deleted file mode 100644 index 68fe2bef7..000000000 --- a/spec/src/main/java/io/a2a/util/Utils.java +++ /dev/null @@ -1,295 +0,0 @@ -package io.a2a.util; - -import static io.a2a.util.Assert.checkNotNullParam; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import com.google.gson.Gson; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Artifact; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import org.jspecify.annotations.Nullable; - -/** - * Utility class providing common helper methods for A2A Protocol operations. - *

      - * This class contains static utility methods for JSON serialization/deserialization, - * null-safe operations, artifact management, and other common tasks used throughout - * the A2A Java SDK. - *

      - * Key capabilities: - *

        - *
      • JSON processing with pre-configured {@link Gson}
      • - *
      • Null-safe value defaults via {@link #defaultIfNull(Object, Object)}
      • - *
      • Artifact streaming support via {@link #appendArtifactToTask(Task, TaskArtifactUpdateEvent, String)}
      • - *
      • Type-safe exception rethrowing via {@link #rethrow(Throwable)}
      • - *
      - * - * @see Gson for JSON processing - * @see TaskArtifactUpdateEvent for streaming artifact updates - */ -public class Utils { - - private static final Logger log = Logger.getLogger(Utils.class.getName()); - - /** - * Private constructor to prevent instantiation of this utility class. - */ - private Utils() { - // Utility class - no instances - } - - /** - * Returns the provided value if non-null, otherwise returns the default value. - *

      - * This is a null-safe utility for providing default values when a parameter - * might be null. - * - * @param the value type - * @param value the value to check - * @param defaultValue the default value to return if value is null - * @return value if non-null, otherwise defaultValue - */ - public static T defaultIfNull(@Nullable T value, T defaultValue) { - return value == null ? defaultValue : value; - } - - /** - * Rethrows a checked exception as an unchecked exception. - *

      - * This method uses type erasure to bypass checked exception handling, - * allowing checked exceptions to be thrown without explicit declaration. - * Use with caution as it bypasses Java's compile-time exception checking. - * - * @param the throwable type - * @param t the throwable to rethrow - * @throws T the rethrown exception - */ - public static void rethrow(Throwable t) throws T { - throw (T) t; - } - - /** - * Appends or updates an artifact in a task based on a {@link TaskArtifactUpdateEvent}. - *

      - * This method handles streaming artifact updates, supporting both: - *

        - *
      • Adding new artifacts to the task
      • - *
      • Replacing existing artifacts (when {@code append=false})
      • - *
      • Appending parts to existing artifacts (when {@code append=true})
      • - *
      - *

      - * The {@code append} flag in the event determines the behavior: - *

        - *
      • {@code false} or {@code null}: Replace/add the entire artifact
      • - *
      • {@code true}: Append the new artifact's parts to an existing artifact with matching {@code artifactId}
      • - *
      - * - * @param task the current task to update - * @param event the artifact update event containing the new/updated artifact - * @param taskId the task ID (for logging purposes) - * @return a new Task instance with the updated artifacts list - * @see TaskArtifactUpdateEvent for streaming artifact updates - * @see Artifact for artifact structure - */ - public static Task appendArtifactToTask(Task task, TaskArtifactUpdateEvent event, String taskId) { - // Append artifacts - List artifacts = task.artifacts() == null ? new ArrayList<>() : new ArrayList<>(task.artifacts()); - - Artifact newArtifact = event.artifact(); - String artifactId = newArtifact.artifactId(); - boolean appendParts = event.append() != null && event.append(); - - Artifact existingArtifact = null; - int existingArtifactIndex = -1; - - for (int i = 0; i < artifacts.size(); i++) { - Artifact curr = artifacts.get(i); - if (curr.artifactId() != null && curr.artifactId().equals(artifactId)) { - existingArtifact = curr; - existingArtifactIndex = i; - break; - } - } - - if (!appendParts) { - // This represents the first chunk for this artifact index - if (existingArtifactIndex >= 0) { - // Replace the existing artifact entirely with the new artifact - log.fine(String.format("Replacing artifact at id %s for task %s", artifactId, taskId)); - artifacts.set(existingArtifactIndex, newArtifact); - } else { - // Append the new artifact since no artifact with this id/index exists yet - log.fine(String.format("Adding artifact at id %s for task %s", artifactId, taskId)); - artifacts.add(newArtifact); - } - - } else if (existingArtifact != null) { - // Append new parts to the existing artifact's parts list - // Do this to a copy - log.fine(String.format("Appending parts to artifact id %s for task %s", artifactId, taskId)); - List> parts = new ArrayList<>(existingArtifact.parts()); - parts.addAll(newArtifact.parts()); - - Map mergedMetadata = null; - if (existingArtifact.metadata() != null || newArtifact.metadata() != null) { - mergedMetadata = new HashMap<>(); - if (existingArtifact.metadata() != null) { - mergedMetadata.putAll(existingArtifact.metadata()); - } - if (newArtifact.metadata() != null) { - mergedMetadata.putAll(newArtifact.metadata()); - } - } - - Artifact updated = Artifact.builder(existingArtifact) - .parts(parts) - .metadata(mergedMetadata) - .build(); - artifacts.set(existingArtifactIndex, updated); - } else { - // We received a chunk to append, but we don't have an existing artifact. - // We will ignore this chunk - log.warning( - String.format("Received append=true for nonexistent artifact index for artifact %s in task %s. Ignoring chunk.", - artifactId, taskId)); - } - - return Task.builder(task) - .artifacts(artifacts) - .build(); - - } - - /** - * Get the first defined URL in the supported interaces of the agent card. - * - * @param agentCard the agentcard where the interfaces are defined. - * @return the first defined URL in the supported interaces of the agent card. - * @throws A2AClientException if no server interface is available in the AgentCard - */ - public static AgentInterface getFavoriteInterface(AgentCard agentCard) throws A2AClientException { - if (agentCard.supportedInterfaces() == null || agentCard.supportedInterfaces().isEmpty()) { - throw new A2AClientException("No server interface available in the AgentCard"); - } - return agentCard.supportedInterfaces().get(0); - } - - /** - * Validates that a tenant path is safe and well-formed. - *

      - * This method performs security validation to prevent: - *

        - *
      • Path traversal attacks (e.g., {@code ../../admin})
      • - *
      • Excessive length (max 256 characters)
      • - *
      • Invalid characters (only allows {@code /a-zA-Z0-9_-.})
      • - *
      - * - * @param tenant the tenant path to validate - * @throws IllegalArgumentException if the tenant is invalid or unsafe - */ - private static void validateTenant(String tenant) { - if (tenant.isEmpty()) { - return; // Empty string is valid (no tenant) - } - - if (tenant.length() > 256) { - throw new IllegalArgumentException("Tenant path exceeds maximum length of 256 characters"); - } - - if (tenant.contains("..")) { - throw new IllegalArgumentException("Tenant path contains invalid '..' sequence (path traversal attempt)"); - } - - if (tenant.contains("//")) { - throw new IllegalArgumentException("Tenant path contains invalid '//' sequence"); - } - - if (!tenant.matches("^[/a-zA-Z0-9_.\\-]+$")) { - throw new IllegalArgumentException("Tenant path contains invalid characters. Only /a-zA-Z0-9_-. are allowed"); - } - } - - /** - * Extracts and normalizes a tenant path, using the agent's default tenant if no override is provided. - *

      - * This method normalizes tenant paths by ensuring they: - *

        - *
      • Start with a forward slash ({@code /})
      • - *
      • Do not end with a forward slash (unless it's just {@code /})
      • - *
      • Are validated for security (no path traversal, length limits, valid characters)
      • - *
      - *

      - * If the provided {@code tenant} parameter is null or blank, the {@code agentTenant} is returned instead. - * - * @param agentTenant the default tenant from the agent card, must not be null - * @param tenant the tenant override from the request, may be null or blank - * @return the normalized tenant path - * @throws IllegalArgumentException if the tenant is invalid or unsafe - */ - private static String extractTenant(String agentTenant, @Nullable String tenant) { - checkNotNullParam("agentTenant", agentTenant); - - String tenantPath = tenant; - if (tenantPath == null || tenantPath.isBlank()) { - return agentTenant; - } - - // Normalize slashes - if (!tenantPath.startsWith("/")) { - tenantPath = '/' + tenantPath; - } - if (tenantPath.endsWith("/") && tenantPath.length() > 1) { - tenantPath = tenantPath.substring(0, tenantPath.length() - 1); - } - - // Validate for security - validateTenant(tenantPath); - - return tenantPath; - } - - /** - * Builds a base URL for A2A operations by combining the agent's URL with a tenant path. - *

      - * This method: - *

        - *
      • Uses the tenant from the {@link AgentInterface} as the default
      • - *
      • Allows overriding with a custom tenant path if provided
      • - *
      • Normalizes trailing slashes on the base URL
      • - *
      • Validates and normalizes the tenant path
      • - *
      - *

      - * Example: - *

      {@code
      -     * AgentInterface iface = new AgentInterface("jsonrpc", "http://example.com", "default-tenant");
      -     * String url = Utils.buildBaseUrl(iface, null);
      -     * // Returns: "http://example.com/default-tenant"
      -     *
      -     * String url2 = Utils.buildBaseUrl(iface, "custom-tenant");
      -     * // Returns: "http://example.com/custom-tenant"
      -     * }
      - * - * @param agentInterface the agent interface containing the base URL and default tenant, must not be null - * @param tenant the tenant override from the request, may be null to use the interface default - * @return the complete base URL with tenant path appended - * @throws IllegalArgumentException if agentInterface is null or tenant validation fails - */ - public static String buildBaseUrl(AgentInterface agentInterface, @Nullable String tenant) { - checkNotNullParam("agentInterface", agentInterface); - - String agentUrl = agentInterface.url(); - agentUrl = agentUrl.endsWith("/") ? agentUrl.substring(0, agentUrl.length() - 1) : agentUrl; - StringBuilder urlBuilder = new StringBuilder(agentUrl); - urlBuilder.append(extractTenant(agentInterface.tenant(), tenant)); - return urlBuilder.toString(); - } -} diff --git a/spec/src/main/java/io/a2a/util/package-info.java b/spec/src/main/java/io/a2a/util/package-info.java deleted file mode 100644 index 78adaa656..000000000 --- a/spec/src/main/java/io/a2a/util/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Utility classes and helpers for the A2A Java SDK. - */ -@NullMarked -package io.a2a.util; - -import org.jspecify.annotations.NullMarked; - diff --git a/spec/src/main/resources/META-INF/beans.xml b/spec/src/main/resources/META-INF/beans.xml deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/src/test/java/io/a2a/util/PageTokenTest.java b/spec/src/test/java/io/a2a/util/PageTokenTest.java deleted file mode 100644 index aef9c8192..000000000 --- a/spec/src/test/java/io/a2a/util/PageTokenTest.java +++ /dev/null @@ -1,161 +0,0 @@ -package io.a2a.util; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.time.Instant; -import java.util.stream.Stream; - -import io.a2a.spec.InvalidParamsError; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.NullAndEmptySource; - -/** - * Unit tests for {@link PageToken}. - */ -class PageTokenTest { - - // ========== Valid Token Parsing Tests ========== - - /** - * Provides test data for valid token parsing tests. - * Format: tokenString, expectedTimestampMillis, expectedId - */ - static Stream validTokens() { - return Stream.of( - Arguments.of("1640000000000:user123", 1640000000000L, "user123"), - Arguments.of("1640000000000:user:123:extra", 1640000000000L, "user:123:extra"), - Arguments.of("0:user123", 0L, "user123"), - Arguments.of("-1000:user123", -1000L, "user123"), - Arguments.of(Long.MAX_VALUE + ":user123", Long.MAX_VALUE, "user123"), - Arguments.of(Long.MIN_VALUE + ":user123", Long.MIN_VALUE, "user123"), - Arguments.of("1640000000000:" + "a".repeat(1000), 1640000000000L, "a".repeat(1000)), - Arguments.of("1640000000000:user-123_test@example.com", 1640000000000L, "user-123_test@example.com") - ); - } - - /** - * Verifies that various valid pageToken strings are correctly parsed into PageToken objects. - */ - @ParameterizedTest - @MethodSource("validTokens") - void testFromString_validTokens_parseCorrectly(String tokenStr, long expectedTimestampMillis, String expectedId) { - PageToken token = PageToken.fromString(tokenStr); - - assertNotNull(token); - assertEquals(Instant.ofEpochMilli(expectedTimestampMillis), token.timestamp()); - assertEquals(expectedId, token.id()); - } - - // ========== Null and Empty Input Tests ========== - - /** - * Verifies that null or empty strings return null instead of throwing an exception. - */ - @ParameterizedTest - @NullAndEmptySource - void testFromString_nullOrEmpty_returnsNull(String tokenStr) { - PageToken token = PageToken.fromString(tokenStr); - assertNull(token); - } - - // ========== Invalid Format Tests ========== - - /** - * Provides test data for invalid token format tests. - * Format: tokenString, expectedErrorMessage - */ - static Stream invalidTokenFormats() { - return Stream.of( - Arguments.of("1640000000000user123", "Invalid pageToken format: expected 'timestamp:id'"), - Arguments.of("1640000000000", "Invalid pageToken format: expected 'timestamp:id'"), - Arguments.of("1640000000000:", "Invalid pageToken format: id part cannot be empty"), - Arguments.of(":", "Invalid pageToken format: timestamp must be numeric milliseconds"), - Arguments.of("notanumber:user123", "Invalid pageToken format: timestamp must be numeric milliseconds"), - Arguments.of("1640000000.123:user123", "Invalid pageToken format: timestamp must be numeric milliseconds"), - Arguments.of("1640 000 000:user123", "Invalid pageToken format: timestamp must be numeric milliseconds") - ); - } - - /** - * Verifies that various invalid token formats throw InvalidParamsError with appropriate messages. - */ - @ParameterizedTest - @MethodSource("invalidTokenFormats") - void testFromString_invalidFormats_throwsInvalidParamsError(String tokenStr, String expectedErrorMessage) { - InvalidParamsError ex = assertThrows(InvalidParamsError.class, () -> { - PageToken.fromString(tokenStr); - }); - assertNotNull(ex.getMessage()); - assertEquals(expectedErrorMessage, ex.getMessage()); - } - - // ========== toString Tests ========== - - /** - * Provides test data for toString tests. - * Format: timestampMillis, id, expectedString - */ - static Stream toStringTestData() { - return Stream.of( - Arguments.of(1640000000000L, "user123", "1640000000000:user123"), - Arguments.of(1640000000000L, "user:123", "1640000000000:user:123"), - Arguments.of(0L, "user123", "0:user123"), - Arguments.of(-1000L, "user123", "-1000:user123") - ); - } - - /** - * Verifies that toString formats PageTokens correctly as "timestamp_millis:id". - */ - @ParameterizedTest - @MethodSource("toStringTestData") - void testToString_formatsCorrectly(long timestampMillis, String id, String expectedString) { - PageToken token = new PageToken(Instant.ofEpochMilli(timestampMillis), id); - String result = token.toString(); - assertEquals(expectedString, result); - } - - // ========== Round-Trip Conversion Tests ========== - - /** - * Provides test data for round-trip conversion tests. - */ - static Stream roundTripTokens() { - return Stream.of( - "1640000000000:user123", - "1640000000000:user:123:extra", - "0:user123", - "-1000:user123" - ); - } - - /** - * Verifies that converting from string to PageToken and back to string preserves the original value. - */ - @ParameterizedTest - @MethodSource("roundTripTokens") - void testRoundTrip_fromStringToString_preservesValue(String original) { - PageToken token = PageToken.fromString(original); - String result = token.toString(); - assertEquals(original, result); - } - - /** - * Verifies that converting from PageToken to string and back to PageToken preserves the original value. - */ - @Test - void testRoundTrip_toStringFromString_preservesValue() { - PageToken original = new PageToken(Instant.ofEpochMilli(1640000000000L), "user123"); - String tokenStr = original.toString(); - PageToken result = PageToken.fromString(tokenStr); - - assertEquals(original.timestamp(), result.timestamp()); - assertEquals(original.id(), result.id()); - } -} diff --git a/spec/src/test/java/io/a2a/util/UtilsTest.java b/spec/src/test/java/io/a2a/util/UtilsTest.java deleted file mode 100644 index d5695a8af..000000000 --- a/spec/src/test/java/io/a2a/util/UtilsTest.java +++ /dev/null @@ -1,193 +0,0 @@ -package io.a2a.util; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.a2a.spec.AgentInterface; -import org.junit.jupiter.api.Test; - -/** - * Unit tests for {@link Utils} tenant-related methods. - */ -class UtilsTest { - - // ========== buildBaseUrl(AgentInterface, String) Tests ========== - - @Test - void testBuildBaseUrl_withAgentInterface_noTenant() { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - String url = Utils.buildBaseUrl(iface, null); - assertEquals("http://example.com", url); - } - - @Test - void testBuildBaseUrl_withAgentInterface_withDefaultTenant() { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", "/default-tenant"); - String url = Utils.buildBaseUrl(iface, null); - assertEquals("http://example.com/default-tenant", url); - } - - @Test - void testBuildBaseUrl_withAgentInterface_withOverrideTenant() { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", "/default-tenant"); - String url = Utils.buildBaseUrl(iface, "/custom-tenant"); - assertEquals("http://example.com/custom-tenant", url); - } - - @Test - void testBuildBaseUrl_withAgentInterface_urlWithTrailingSlash() { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com/", "/tenant"); - String url = Utils.buildBaseUrl(iface, null); - assertEquals("http://example.com/tenant", url); - } - - @Test - void testBuildBaseUrl_withAgentInterface_urlWithoutTrailingSlash() { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", "/tenant"); - String url = Utils.buildBaseUrl(iface, null); - assertEquals("http://example.com/tenant", url); - } - - @Test - void testBuildBaseUrl_withAgentInterface_nullInterface_throws() { - assertThrows(IllegalArgumentException.class, () -> { - Utils.buildBaseUrl(null, "/tenant"); - }); - } - - // ========== Security Validation Tests ========== - - @Test - void testValidateTenant_pathTraversal_throws() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - Utils.buildBaseUrl(iface, "../../admin"); - }); - assertNotNull(ex.getMessage()); - assertEquals("Tenant path contains invalid '..' sequence (path traversal attempt)", ex.getMessage()); - } - - @Test - void testValidateTenant_pathTraversalWithSlash_throws() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - Utils.buildBaseUrl(iface, "/../admin"); - }); - assertNotNull(ex.getMessage()); - assertEquals("Tenant path contains invalid '..' sequence (path traversal attempt)", ex.getMessage()); - } - - @Test - void testValidateTenant_tooLong_throws() { - String longTenant = "/" + "a".repeat(256); - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - Utils.buildBaseUrl(iface, longTenant); - }); - assertNotNull(ex.getMessage()); - assertEquals("Tenant path exceeds maximum length of 256 characters", ex.getMessage()); - } - - @Test - void testValidateTenant_maxLengthAllowed_succeeds() { - // 256 characters total (including leading slash) - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - String maxTenant = "/" + "a".repeat(255); - String url = Utils.buildBaseUrl(iface, maxTenant); - assertNotNull(url); - assertEquals("http://example.com/" + "a".repeat(255), url); - } - - @Test - void testValidateTenant_invalidCharactersSpace_throws() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - Utils.buildBaseUrl(iface, "/tenant with spaces"); - }); - assertNotNull(ex.getMessage()); - assertEquals("Tenant path contains invalid characters. Only /a-zA-Z0-9_-. are allowed", ex.getMessage()); - } - - @Test - void testValidateTenant_invalidCharactersSpecial_throws() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - Utils.buildBaseUrl(iface, "/tenant@123"); - }); - assertNotNull(ex.getMessage()); - assertEquals("Tenant path contains invalid characters. Only /a-zA-Z0-9_-. are allowed", ex.getMessage()); - } - - @Test - void testValidateTenant_invalidCharactersQuery_throws() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - Utils.buildBaseUrl(iface, "/tenant?param=value"); - }); - assertNotNull(ex.getMessage()); - assertEquals("Tenant path contains invalid characters. Only /a-zA-Z0-9_-. are allowed", ex.getMessage()); - } - - @Test - void testValidateTenant_validCharacters_succeeds() { - // Test all allowed characters: /a-zA-Z0-9_-. - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - String url1 = Utils.buildBaseUrl(iface, "/tenant-name"); - assertEquals("http://example.com/tenant-name", url1); - - String url2 = Utils.buildBaseUrl(iface, "/tenant_name"); - assertEquals("http://example.com/tenant_name", url2); - - String url3 = Utils.buildBaseUrl(iface, "/Tenant123"); - assertEquals("http://example.com/Tenant123", url3); - - String url4 = Utils.buildBaseUrl(iface, "/multi/level/tenant"); - assertEquals("http://example.com/multi/level/tenant", url4); - - String url5 = Utils.buildBaseUrl(iface, "/tenant.v1"); - assertEquals("http://example.com/tenant.v1", url5); - - String url6 = Utils.buildBaseUrl(iface, "/.well-known"); - assertEquals("http://example.com/.well-known", url6); - } - - @Test - void testValidateTenant_emptyString_succeeds() { - // Empty string is valid (no tenant) - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - String url = Utils.buildBaseUrl(iface, ""); - assertEquals("http://example.com", url); - } - - @Test - void testValidateTenant_multiLevelTenant_succeeds() { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com", ""); - String url = Utils.buildBaseUrl(iface, "/org/team/tenant"); - assertEquals("http://example.com/org/team/tenant", url); - } - - // ========== Edge Case Tests ========== - - @Test - void testBuildBaseUrl_complexScenario() { - // Base URL with trailing slash, default tenant, custom override - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com:8080/api/", "/default"); - String url = Utils.buildBaseUrl(iface, "custom-tenant"); - assertEquals("http://example.com:8080/api/custom-tenant", url); - } - - @Test - void testBuildBaseUrl_urlWithPort() { - AgentInterface iface = new AgentInterface("JSONRPC", "http://example.com:9999", "/tenant"); - String url = Utils.buildBaseUrl(iface, null); - assertEquals("http://example.com:9999/tenant", url); - } - - @Test - void testBuildBaseUrl_httpsUrl() { - AgentInterface iface = new AgentInterface("JSONRPC", "https://secure.example.com", "/tenant"); - String url = Utils.buildBaseUrl(iface, null); - assertEquals("https://secure.example.com/tenant", url); - } -} diff --git a/tck/pom.xml b/tck/pom.xml deleted file mode 100644 index e7f7cefcd..000000000 --- a/tck/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - - - a2a-tck-server - - Java SDK A2A TCK Server - Server example to use with the A2A TCK - - - - ${project.groupId} - a2a-java-sdk-reference-jsonrpc - - - io.github.a2asdk - a2a-java-sdk-reference-grpc - - - io.github.a2asdk - a2a-java-sdk-reference-rest - - - io.quarkus - quarkus-rest - provided - - - jakarta.enterprise - jakarta.enterprise.cdi-api - provided - - - jakarta.ws.rs - jakarta.ws.rs-api - - - - - - - io.quarkus - quarkus-maven-plugin - true - - - - build - generate-code - generate-code-tests - - - - - - - diff --git a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java deleted file mode 100644 index 571e2bb1f..000000000 --- a/tck/src/main/java/io/a2a/tck/server/AgentCardProducer.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.a2a.tck.server; - - -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.AgentInterface; -import io.a2a.spec.AgentSkill; -import io.a2a.spec.TransportProtocol; - -@ApplicationScoped -public class AgentCardProducer { - - private static final String DEFAULT_SUT_URL = "http://localhost:9999"; - - @Produces - @PublicAgentCard - public AgentCard agentCard() { - - String sutJsonRpcUrl = getEnvOrDefault("SUT_JSONRPC_URL", DEFAULT_SUT_URL); - String sutGrpcUrl = getEnvOrDefault("SUT_GRPC_URL", DEFAULT_SUT_URL); - String sutRestcUrl = getEnvOrDefault("SUT_REST_URL", DEFAULT_SUT_URL); - return AgentCard.builder() - .name("Hello World Agent") - .description("Just a hello world agent") - .supportedInterfaces(List.of( - new AgentInterface(TransportProtocol.JSONRPC.asString(), sutJsonRpcUrl), - new AgentInterface(TransportProtocol.GRPC.asString(), sutGrpcUrl), - new AgentInterface(TransportProtocol.HTTP_JSON.asString(), sutRestcUrl))) - .version("1.0.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(Collections.singletonList(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(); - } - - private static String getEnvOrDefault(String envVar, String defaultValue) { - String value = System.getenv(envVar); - return value == null || value.isBlank() ? defaultValue : value; - } -} - diff --git a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java deleted file mode 100644 index b69a902e4..000000000 --- a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java +++ /dev/null @@ -1,100 +0,0 @@ -package io.a2a.tck.server; - -import java.util.List; - -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.tasks.AgentEmitter; -import io.a2a.spec.A2AError; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; - -@ApplicationScoped -public class AgentExecutorProducer { - - @Produces - public AgentExecutor agentExecutor() { - return new FireAndForgetAgentExecutor(); - } - - private static class FireAndForgetAgentExecutor implements AgentExecutor { - - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - Task task = context.getTask(); - - if (task == null) { - if (context == null) { - throw new IllegalArgumentException("RequestContext may not be null"); - } - if (context.getTaskId() == null) { - throw new IllegalArgumentException("Parameter 'id' may not be null"); - } - if (context.getContextId() == null) { - throw new IllegalArgumentException("Parameter 'contextId' may not be null"); - } - task = Task.builder() - .id(context.getTaskId()) - .contextId(context.getContextId()) - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .history(List.of(context.getMessage())) - .build(); - agentEmitter.addTask(task); - } - - // Sleep to allow task state persistence before TCK subscribe test - if (context.getMessage() != null && context.getMessage().messageId().startsWith("test-subscribe-message-id")) { - int timeoutMs = Integer.parseInt(System.getenv().getOrDefault("RESUBSCRIBE_TIMEOUT_MS", "3000")); - System.out.println("====> task id starts with test-subscribe-message-id, sleeping for " + timeoutMs + " ms"); - try { - Thread.sleep(timeoutMs); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - // Immediately set to WORKING state - agentEmitter.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, AgentEmitter agentEmitter) throws A2AError { - System.out.println("====> task cancel request received"); - Task task = context.getTask(); - if (task == null) { - System.out.println("====> No task found"); - throw new TaskNotCancelableError(); - } - if (task.status().state() == TaskState.TASK_STATE_CANCELED) { - System.out.println("====> task already canceled"); - throw new TaskNotCancelableError(); - } - - if (task.status().state() == TaskState.TASK_STATE_COMPLETED) { - System.out.println("====> task already completed"); - throw new TaskNotCancelableError(); - } - - agentEmitter.cancel(); - System.out.println("====> task canceled"); - } - - /** - * Cleanup method for proper resource management - */ - @PreDestroy - public void cleanup() { - System.out.println("====> shutting down task executor"); - } - } -} diff --git a/tck/src/main/java/io/a2a/tck/server/package-info.java b/tck/src/main/java/io/a2a/tck/server/package-info.java deleted file mode 100644 index f2b9319f2..000000000 --- a/tck/src/main/java/io/a2a/tck/server/package-info.java +++ /dev/null @@ -1,10 +0,0 @@ -@NullMarked -package io.a2a.tck.server; - -import org.jspecify.annotations.NullMarked; - -//The following had @Nullable annotation applied from JSpecify -//AgentCardProducer.java getEnvOrDefault method, -//AgentExecutorProducer.java execute method -// - diff --git a/tck/src/main/resources/application.properties b/tck/src/main/resources/application.properties deleted file mode 100644 index b23747b00..000000000 --- a/tck/src/main/resources/application.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Use the new gRPC implementation which uses the main HTTP port -quarkus.grpc.server.use-separate-server=false -%dev.quarkus.http.port=9999 - -# Thread pool configuration for TCK testing -# Limit max threads to prevent resource exhaustion in CI environments -a2a.executor.core-pool-size=5 -a2a.executor.max-pool-size=15 -a2a.executor.keep-alive-seconds=60 - -# Enable debug logging for troubleshooting TCK failures -quarkus.log.category."io.a2a.server.requesthandlers".level=DEBUG -quarkus.log.category."io.a2a.server.events".level=DEBUG -quarkus.log.category."io.a2a.server.tasks".level=DEBUG -io.a2a.server.diagnostics.ThreadStats.level=DEBUG - -# Log to file for analysis -quarkus.log.file.enable=true -quarkus.log.file.path=target/tck-test.log -quarkus.log.file.level=DEBUG -quarkus.log.console.level=INFO diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml deleted file mode 100644 index 5d091ee23..000000000 --- a/tests/server-common/pom.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-tests-server-common - - jar - - Java A2A SDK Server Tests Common - Java SDK for the Agent2Agent Protocol (A2A) - SDK - Server Tests Common - - - - ${project.groupId} - a2a-java-sdk-spec - - - ${project.groupId} - a2a-java-sdk-client - - - ${project.groupId} - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - jakarta.ws.rs - jakarta.ws.rs-api - test - - - org.junit.jupiter - junit-jupiter-api - test - - - io.rest-assured - rest-assured - test - - - io.quarkus - quarkus-arc - test - - - io.github.a2asdk - a2a-java-sdk-client-transport-jsonrpc - test - - - io.github.a2asdk - a2a-java-sdk-client-transport-grpc - test - - - io.github.a2asdk - a2a-java-sdk-client-transport-rest - test - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - - \ No newline at end of file diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java deleted file mode 100644 index c64e5051c..000000000 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ -package io.a2a.server.apps.common; - -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.restassured.mapper.ObjectMapper; -import io.restassured.mapper.ObjectMapperDeserializationContext; -import io.restassured.mapper.ObjectMapperSerializationContext; - - -public class A2AGsonObjectMapper implements ObjectMapper { - public static final A2AGsonObjectMapper INSTANCE = new A2AGsonObjectMapper(); - - private A2AGsonObjectMapper() { - } - - @Override - public Object deserialize(ObjectMapperDeserializationContext context) { - try { - return JsonUtil.fromJson(context.getDataToDeserialize().asString(), context.getType()); - } catch (JsonProcessingException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public Object serialize(ObjectMapperSerializationContext context) { - try { - return JsonUtil.toJson(context.getObjectToSerialize()); - } catch (JsonProcessingException ex) { - - throw new RuntimeException(ex); - } - } -} diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java deleted file mode 100644 index 75ba229ea..000000000 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java +++ /dev/null @@ -1,2597 +0,0 @@ -package io.a2a.server.apps.common; - -import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; - -import java.io.EOFException; -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jakarta.ws.rs.core.MediaType; - -import io.a2a.client.Client; -import io.a2a.client.ClientBuilder; -import io.a2a.client.ClientEvent; -import io.a2a.client.MessageEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; -import io.a2a.jsonrpc.common.wrappers.StreamingJSONRPCRequest; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Artifact; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.Event; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.Part; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.UnsupportedOperationError; - -import io.restassured.RestAssured; -import io.restassured.config.ObjectMapperConfig; -import io.restassured.specification.RequestSpecification; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; - -/** - * This test requires doing some work on the server to add/get/delete tasks, and enqueue events. This is exposed via - * REST, - * which delegates to {@link TestUtilsBean}. - */ -public abstract class AbstractA2AServerTest { - - protected static final Task MINIMAL_TASK = Task.builder() - .id("task-123") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - private static final Task CANCEL_TASK = Task.builder() - .id("cancel-task-123") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - private static final Task CANCEL_TASK_NOT_SUPPORTED = Task.builder() - .id("cancel-task-not-supported-123") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - private static final Task SEND_MESSAGE_NOT_SUPPORTED = Task.builder() - .id("task-not-supported-123") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - protected static final Message MESSAGE = Message.builder() - .messageId("111") - .role(Message.Role.ROLE_AGENT) - .parts(new TextPart("test message")) - .build(); - public static final String APPLICATION_JSON = "application/json"; - - public static RequestSpecification given() { - return RestAssured.given() - .config(RestAssured.config() - .objectMapperConfig(new ObjectMapperConfig(A2AGsonObjectMapper.INSTANCE))); -} - - - protected final int serverPort; - private Client client; - private Client nonStreamingClient; - private Client pollingClient; - - protected AbstractA2AServerTest(int serverPort) { - this.serverPort = serverPort; - } - - /** - * Get the transport protocol to use for this test (e.g., "JSONRPC", "GRPC"). - */ - protected abstract String getTransportProtocol(); - - /** - * Get the transport URL for this test. - */ - protected abstract String getTransportUrl(); - - /** - * Get the transport configs to use for this test. - */ - protected abstract void configureTransport(ClientBuilder builder); - - @Test - public void testTaskStoreMethodsSanityTest() throws Exception { - Task task = Task.builder(MINIMAL_TASK).id("abcde").build(); - saveTaskInTaskStore(task); - Task saved = getTaskFromTaskStore(task.id()); - assertEquals(task.id(), saved.id()); - assertEquals(task.contextId(), saved.contextId()); - assertEquals(task.status().state(), saved.status().state()); - - deleteTaskInTaskStore(task.id()); - Task saved2 = getTaskFromTaskStore(task.id()); - assertNull(saved2); - } - - @Test - public void testGetTaskSuccess() throws Exception { - testGetTask(); - } - - private void testGetTask() throws Exception { - testGetTask(null); - } - - private void testGetTask(String mediaType) throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - Task response = getClient().getTask(new TaskQueryParams(MINIMAL_TASK.id())); - assertEquals("task-123", response.id()); - assertEquals("session-xyz", response.contextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, response.status().state()); - } catch (A2AClientException e) { - fail("Unexpected exception during getTask: " + e.getMessage(), e); - } finally { - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testGetTaskNotFound() throws Exception { - assertTrue(getTaskFromTaskStore("non-existent-task") == null); - try { - getClient().getTask(new TaskQueryParams("non-existent-task")); - fail("Expected A2AClientException for non-existent task"); - } catch (A2AClientException e) { - // Expected - the client should throw an exception for non-existent tasks - assertInstanceOf(TaskNotFoundError.class, e.getCause()); - } - } - - @Test - public void testCancelTaskSuccess() throws Exception { - saveTaskInTaskStore(CANCEL_TASK); - try { - Task task = getClient().cancelTask(new TaskIdParams(CANCEL_TASK.id())); - assertEquals(CANCEL_TASK.id(), task.id()); - assertEquals(CANCEL_TASK.contextId(), task.contextId()); - assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); - } catch (A2AClientException e) { - fail("Unexpected exception during cancel task: " + e.getMessage(), e); - } finally { - deleteTaskInTaskStore(CANCEL_TASK.id()); - } - } - - @Test - public void testCancelTaskNotSupported() throws Exception { - saveTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED); - try { - getClient().cancelTask(new TaskIdParams(CANCEL_TASK_NOT_SUPPORTED.id())); - fail("Expected A2AClientException for unsupported cancel operation"); - } catch (A2AClientException e) { - // Expected - the client should throw an exception for unsupported operations - assertInstanceOf(UnsupportedOperationError.class, e.getCause()); - } finally { - deleteTaskInTaskStore(CANCEL_TASK_NOT_SUPPORTED.id()); - } - } - - @Test - public void testCancelTaskNotFound() { - try { - getClient().cancelTask(new TaskIdParams("non-existent-task")); - fail("Expected A2AClientException for non-existent task"); - } catch (A2AClientException e) { - // Expected - the client should throw an exception for non-existent tasks - assertInstanceOf(TaskNotFoundError.class, e.getCause()); - } - } - - @Test - public void testListTasksSuccess() throws Exception { - // Create multiple tasks with different contexts and states - Task task1 = Task.builder() - .id("list-task-1") - .contextId("context-1") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - Task task2 = Task.builder() - .id("list-task-2") - .contextId("context-1") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - Task task3 = Task.builder() - .id("list-task-3") - .contextId("context-2") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - saveTaskInTaskStore(task1); - saveTaskInTaskStore(task2); - saveTaskInTaskStore(task3); - - try { - // Test listing all tasks (no filters) - io.a2a.spec.ListTasksParams params = ListTasksParams.builder().tenant("").build(); - ListTasksResult result = getClient().listTasks(params); - - assertNotNull(result); - assertNotNull(result.tasks()); - assertTrue(result.tasks().size() >= 3, "Should have at least 3 tasks"); - assertEquals(result.tasks().size(), result.pageSize()); - assertTrue(result.totalSize() >= 3, "Total size should be at least 3"); - } finally { - deleteTaskInTaskStore(task1.id()); - deleteTaskInTaskStore(task2.id()); - deleteTaskInTaskStore(task3.id()); - } - } - - @Test - public void testListTasksFilterByContextId() throws Exception { - Task task1 = Task.builder() - .id("list-task-ctx-1") - .contextId("context-filter-1") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - Task task2 = Task.builder() - .id("list-task-ctx-2") - .contextId("context-filter-1") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - Task task3 = Task.builder() - .id("list-task-ctx-3") - .contextId("context-filter-2") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - saveTaskInTaskStore(task1); - saveTaskInTaskStore(task2); - saveTaskInTaskStore(task3); - - try { - // Filter by contextId - io.a2a.spec.ListTasksParams params = ListTasksParams.builder() - .contextId("context-filter-1") - .tenant("") - .build(); - ListTasksResult result = getClient().listTasks(params); - - assertNotNull(result); - assertNotNull(result.tasks()); - assertEquals(2, result.tasks().size(), "Should have exactly 2 tasks with context-filter-1"); - assertTrue(result.tasks().stream().allMatch(t -> "context-filter-1".equals(t.contextId()))); - } finally { - deleteTaskInTaskStore(task1.id()); - deleteTaskInTaskStore(task2.id()); - deleteTaskInTaskStore(task3.id()); - } - } - - @Test - public void testListTasksFilterByStatus() throws Exception { - Task task1 = Task.builder() - .id("list-task-status-1") - .contextId("context-status") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - Task task2 = Task.builder() - .id("list-task-status-2") - .contextId("context-status") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - Task task3 = Task.builder() - .id("list-task-status-3") - .contextId("context-status") - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - saveTaskInTaskStore(task1); - saveTaskInTaskStore(task2); - saveTaskInTaskStore(task3); - - try { - // Filter by status WORKING - io.a2a.spec.ListTasksParams params = ListTasksParams.builder() - .status(TaskState.TASK_STATE_WORKING) - .tenant("") - .build(); - ListTasksResult result = getClient().listTasks(params); - - assertNotNull(result); - assertNotNull(result.tasks()); - assertTrue(result.tasks().size() >= 2, "Should have at least 2 WORKING tasks"); - assertTrue(result.tasks().stream() - .filter(t -> t.id().startsWith("list-task-status-")) - .allMatch(t -> TaskState.TASK_STATE_WORKING.equals(t.status().state()))); - } finally { - deleteTaskInTaskStore(task1.id()); - deleteTaskInTaskStore(task2.id()); - deleteTaskInTaskStore(task3.id()); - } - } - - @Test - public void testListTasksWithPagination() throws Exception { - // Create several tasks - Task task1 = Task.builder() - .id("page-task-1") - .contextId("page-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - Task task2 = Task.builder() - .id("page-task-2") - .contextId("page-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - Task task3 = Task.builder() - .id("page-task-3") - .contextId("page-context") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build(); - - saveTaskInTaskStore(task1); - saveTaskInTaskStore(task2); - saveTaskInTaskStore(task3); - - try { - // Get first page with pageSize=2 - io.a2a.spec.ListTasksParams params1 = ListTasksParams.builder() - .contextId("page-context") - .tenant("") - .pageSize(2) - .build(); - ListTasksResult result1 = getClient().listTasks(params1); - - assertNotNull(result1); - assertEquals(2, result1.tasks().size(), "First page should have 2 tasks"); - assertNotNull(result1.nextPageToken(), "Should have next page token"); - assertTrue(result1.hasMoreResults()); - - // Get second page using pageToken - io.a2a.spec.ListTasksParams params2 = ListTasksParams.builder() - .contextId("page-context") - .tenant("") - .pageSize(2) - .pageToken(result1.nextPageToken()) - .build(); - ListTasksResult result2 = getClient().listTasks(params2); - - assertNotNull(result2); - assertTrue(result2.tasks().size() >= 1, "Second page should have at least 1 task"); - } finally { - deleteTaskInTaskStore(task1.id()); - deleteTaskInTaskStore(task2.id()); - deleteTaskInTaskStore(task3.id()); - } - } - - @Test - public void testListTasksWithHistoryLimit() throws Exception { - // Create task with multiple history messages - List history = List.of( - Message.builder(MESSAGE).messageId("msg-1").build(), - Message.builder(MESSAGE).messageId("msg-2").build(), - Message.builder(MESSAGE).messageId("msg-3").build(), - Message.builder(MESSAGE).messageId("msg-4").build() - ); - Task taskWithHistory = Task.builder() - .id("list-task-history") - .contextId("context-history") - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .history(history) - .build(); - - saveTaskInTaskStore(taskWithHistory); - - try { - // List with history limited to 2 messages - io.a2a.spec.ListTasksParams params = ListTasksParams.builder() - .contextId("context-history") - .tenant("") - .historyLength(2) - .build(); - ListTasksResult result = getClient().listTasks(params); - - assertNotNull(result); - assertEquals(1, result.tasks().size()); - Task task = result.tasks().get(0); - assertNotNull(task.history()); - assertEquals(2, task.history().size(), "History should be limited to 2 most recent messages"); - // Verify we get the most recent messages (msg-3 and msg-4) - assertEquals("msg-3", task.history().get(0).messageId()); - assertEquals("msg-4", task.history().get(1).messageId()); - } finally { - deleteTaskInTaskStore(taskWithHistory.id()); - } - } - - @Test - public void testSendMessageNewMessageSuccess() throws Exception { - assertTrue(getTaskFromTaskStore(MINIMAL_TASK.id()) == null); - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - CountDownLatch latch = new CountDownLatch(1); - AtomicReference receivedMessage = new AtomicReference<>(); - AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); - BiConsumer consumer = (event, agentCard) -> { - if (event instanceof MessageEvent messageEvent) { - if (latch.getCount() > 0) { - receivedMessage.set(messageEvent.getMessage()); - latch.countDown(); - } else { - wasUnexpectedEvent.set(true); - } - } else { - wasUnexpectedEvent.set(true); - } - }; - - // testing the non-streaming send message - getNonStreamingClient().sendMessage(message, List.of(consumer), null); - - assertTrue(latch.await(10, TimeUnit.SECONDS)); - assertFalse(wasUnexpectedEvent.get()); - Message messageResponse = receivedMessage.get(); - assertNotNull(messageResponse); - assertEquals(MESSAGE.messageId(), messageResponse.messageId()); - assertEquals(MESSAGE.role(), messageResponse.role()); - Part part = messageResponse.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("test message", ((TextPart) part).text()); - } - - @Test - public void testSendMessageExistingTaskSuccess() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - CountDownLatch latch = new CountDownLatch(1); - AtomicReference receivedMessage = new AtomicReference<>(); - AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); - BiConsumer consumer = (event, agentCard) -> { - if (event instanceof MessageEvent messageEvent) { - if (latch.getCount() > 0) { - receivedMessage.set(messageEvent.getMessage()); - latch.countDown(); - } else { - wasUnexpectedEvent.set(true); - } - } else { - wasUnexpectedEvent.set(true); - } - }; - - // testing the non-streaming send message - getNonStreamingClient().sendMessage(message, List.of(consumer), null); - assertFalse(wasUnexpectedEvent.get()); - assertTrue(latch.await(10, TimeUnit.SECONDS)); - Message messageResponse = receivedMessage.get(); - assertNotNull(messageResponse); - assertEquals(MESSAGE.messageId(), messageResponse.messageId()); - assertEquals(MESSAGE.role(), messageResponse.role()); - Part part = messageResponse.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("test message", ((TextPart) part).text()); - } catch (A2AClientException e) { - fail("Unexpected exception during sendMessage: " + e.getMessage(), e); - } finally { - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testSetPushNotificationSuccess() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); - TaskPushNotificationConfig config = getClient().createTaskPushNotificationConfiguration(taskPushConfig); - assertEquals(MINIMAL_TASK.id(), config.taskId()); - assertEquals("http://example.com", config.config().url()); - assertEquals("c295ea44-7543-4f78-b524-7a38915ad6e4", config.config().id()); - } catch (A2AClientException e) { - fail("Unexpected exception during set push notification test: " + e.getMessage(), e); - } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "c295ea44-7543-4f78-b524-7a38915ad6e4"); - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testGetPushNotificationSuccess() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); - - TaskPushNotificationConfig setResult = getClient().createTaskPushNotificationConfiguration(taskPushConfig); - assertNotNull(setResult); - - TaskPushNotificationConfig config = getClient().getTaskPushNotificationConfiguration( - new GetTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "c295ea44-7543-4f78-b524-7a38915ad6e4")); - assertEquals(MINIMAL_TASK.id(), config.taskId()); - assertEquals("http://example.com", config.config().url()); - } catch (A2AClientException e) { - fail("Unexpected exception during get push notification test: " + e.getMessage(), e); - } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "c295ea44-7543-4f78-b524-7a38915ad6e4"); - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testError() throws A2AClientException { - Message message = Message.builder(MESSAGE) - .taskId(SEND_MESSAGE_NOT_SUPPORTED.id()) - .contextId(SEND_MESSAGE_NOT_SUPPORTED.contextId()) - .build(); - - try { - getNonStreamingClient().sendMessage(message); - - // For non-streaming clients, the error should still be thrown as an exception - fail("Expected A2AClientException for unsupported send message operation"); - } catch (A2AClientException e) { - // Expected - the client should throw an exception for unsupported operations - assertInstanceOf(UnsupportedOperationError.class, e.getCause()); - } - } - - @Test - public void testGetExtendedAgentCard() throws A2AClientException { - AgentCard agentCard = getClient().getExtendedAgentCard(); - assertNotNull(agentCard); - assertEquals("test-card", agentCard.name()); - assertEquals("A test agent card", agentCard.description()); - assertNotNull(agentCard.supportedInterfaces()); - assertFalse(agentCard.supportedInterfaces().isEmpty()); - Optional transportInterface = agentCard.supportedInterfaces().stream() - .filter(i -> getTransportProtocol().equals(i.protocolBinding())) - .findFirst(); - assertTrue(transportInterface.isPresent()); - assertEquals(getTransportUrl(),transportInterface.get().url()); - assertEquals("1.0", agentCard.version()); - assertEquals("http://example.com/docs", agentCard.documentationUrl()); - assertTrue(agentCard.capabilities().pushNotifications()); - assertTrue(agentCard.capabilities().streaming()); - assertTrue(agentCard.capabilities().extendedAgentCard()); - assertTrue(agentCard.skills().isEmpty()); - } - - @Test - public void testSendMessageStreamNewMessageSuccess() throws Exception { - testSendStreamingMessage(false); - } - - @Test - public void testSendMessageStreamExistingTaskSuccess() throws Exception { - testSendStreamingMessage(true); - } - - @Test - @Timeout(value = 3, unit = TimeUnit.MINUTES) - public void testSubscribeExistingTaskSuccess() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - // attempting to send a streaming message instead of explicitly calling queueManager#createOrTap - // does not work because after the message is sent, the queue becomes null but task resubscription - // requires the queue to still be active - ensureQueueForTask(MINIMAL_TASK.id()); - - CountDownLatch eventLatch = new CountDownLatch(2); - AtomicReference artifactUpdateEvent = new AtomicReference<>(); - AtomicReference statusUpdateEvent = new AtomicReference<>(); - AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); - AtomicReference errorRef = new AtomicReference<>(); - - // Create consumer to handle subscribed events - AtomicBoolean receivedInitialTask = new AtomicBoolean(false); - BiConsumer consumer = (event, agentCard) -> { - // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent - if (!receivedInitialTask.get()) { - if (event instanceof TaskEvent) { - receivedInitialTask.set(true); - // Don't count down latch for initial Task - return; - } else { - fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); - } - } - - // Process subsequent events - if (event instanceof TaskUpdateEvent taskUpdateEvent) { - if (taskUpdateEvent.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifactEvent) { - artifactUpdateEvent.set(artifactEvent); - eventLatch.countDown(); - } else if (taskUpdateEvent.getUpdateEvent() instanceof TaskStatusUpdateEvent statusEvent) { - statusUpdateEvent.set(statusEvent); - eventLatch.countDown(); - } else { - wasUnexpectedEvent.set(true); - } - } else { - wasUnexpectedEvent.set(true); - } - }; - - // Create error handler - Consumer errorHandler = error -> { - if (!isStreamClosedError(error)) { - errorRef.set(error); - } - eventLatch.countDown(); - }; - - // Count down when the streaming subscription is established - CountDownLatch subscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); - - // subscribe to the task with specific consumer and error handler - getClient().subscribeToTask(new TaskIdParams(MINIMAL_TASK.id()), List.of(consumer), errorHandler); - - // Wait for subscription to be established - assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); - - // Enqueue events on the server - List events = List.of( - TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); - - for (Event event : events) { - enqueueEventOnServer(event); - } - - // Wait for events to be received - assertTrue(eventLatch.await(30, TimeUnit.SECONDS)); - assertFalse(wasUnexpectedEvent.get()); - assertNull(errorRef.get()); - - // Verify artifact update event - TaskArtifactUpdateEvent receivedArtifactEvent = artifactUpdateEvent.get(); - assertNotNull(receivedArtifactEvent); - assertEquals(MINIMAL_TASK.id(), receivedArtifactEvent.taskId()); - assertEquals(MINIMAL_TASK.contextId(), receivedArtifactEvent.contextId()); - Part part = receivedArtifactEvent.artifact().parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("text", ((TextPart) part).text()); - - // Verify status update event - TaskStatusUpdateEvent receivedStatusEvent = statusUpdateEvent.get(); - assertNotNull(receivedStatusEvent); - assertEquals(MINIMAL_TASK.id(), receivedStatusEvent.taskId()); - assertEquals(MINIMAL_TASK.contextId(), receivedStatusEvent.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, receivedStatusEvent.status().state()); - assertNotNull(receivedStatusEvent.status().timestamp()); - } finally { - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - @Timeout(value = 3, unit = TimeUnit.MINUTES) - public void testSubscribeExistingTaskSuccessWithClientConsumers() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - // attempting to send a streaming message instead of explicitly calling queueManager#createOrTap - // does not work because after the message is sent, the queue becomes null but task resubscription - // requires the queue to still be active - ensureQueueForTask(MINIMAL_TASK.id()); - - CountDownLatch eventLatch = new CountDownLatch(2); - AtomicReference artifactUpdateEvent = new AtomicReference<>(); - AtomicReference statusUpdateEvent = new AtomicReference<>(); - AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); - AtomicReference errorRef = new AtomicReference<>(); - - // Create consumer to handle subscribed events - AtomicBoolean receivedInitialTask = new AtomicBoolean(false); - - AgentCard agentCard = createTestAgentCard(); - ClientConfig clientConfig = createClientConfig(true); - ClientBuilder clientBuilder = Client - .builder(agentCard) - .addConsumer((evt, agentCard1) -> { - // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent - if (!receivedInitialTask.get()) { - if (evt instanceof TaskEvent) { - receivedInitialTask.set(true); - // Don't count down latch for initial Task - return; - } else { - fail("First event on subscribe MUST be TaskEvent, but was: " + evt.getClass().getSimpleName()); - } - } - - // Process subsequent events - if (evt instanceof TaskUpdateEvent taskUpdateEvent) { - if (taskUpdateEvent.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifactEvent) { - artifactUpdateEvent.set(artifactEvent); - eventLatch.countDown(); - } else if (taskUpdateEvent.getUpdateEvent() instanceof TaskStatusUpdateEvent statusEvent) { - statusUpdateEvent.set(statusEvent); - eventLatch.countDown(); - } else { - wasUnexpectedEvent.set(true); - } - } else { - wasUnexpectedEvent.set(true); - } - }) - .streamingErrorHandler(error -> { - if (!isStreamClosedError(error)) { - errorRef.set(error); - } - eventLatch.countDown(); - }) - .clientConfig(clientConfig); - configureTransport(clientBuilder); - - Client clientWithConsumer = clientBuilder.build(); - - // Count down when the streaming subscription is established - CountDownLatch subscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); - - // Subscribe to the task with the client consumer and error handler - clientWithConsumer.subscribeToTask(new TaskIdParams(MINIMAL_TASK.id())); - - // Wait for subscription to be established - assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); - - // Enqueue events on the server - List events = List.of( - TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); - - for (Event event : events) { - enqueueEventOnServer(event); - } - - // Wait for events to be received - assertTrue(eventLatch.await(30, TimeUnit.SECONDS)); - assertFalse(wasUnexpectedEvent.get()); - assertNull(errorRef.get()); - - // Verify artifact update event - TaskArtifactUpdateEvent receivedArtifactEvent = artifactUpdateEvent.get(); - assertNotNull(receivedArtifactEvent); - assertEquals(MINIMAL_TASK.id(), receivedArtifactEvent.taskId()); - assertEquals(MINIMAL_TASK.contextId(), receivedArtifactEvent.contextId()); - Part part = receivedArtifactEvent.artifact().parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("text", ((TextPart) part).text()); - - // Verify status update event - TaskStatusUpdateEvent receivedStatusEvent = statusUpdateEvent.get(); - assertNotNull(receivedStatusEvent); - assertEquals(MINIMAL_TASK.id(), receivedStatusEvent.taskId()); - assertEquals(MINIMAL_TASK.contextId(), receivedStatusEvent.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, receivedStatusEvent.status().state()); - assertNotNull(receivedStatusEvent.status().timestamp()); - } finally { - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testSubscribeNoExistingTaskError() throws Exception { - CountDownLatch errorLatch = new CountDownLatch(1); - AtomicReference errorRef = new AtomicReference<>(); - - // Create error handler to capture the TaskNotFoundError - Consumer errorHandler = error -> { - if (error == null) { - // Stream completed successfully - ignore, we're waiting for an error - return; - } - if (!isStreamClosedError(error)) { - errorRef.set(error); - } - errorLatch.countDown(); - }; - - try { - getClient().subscribeToTask(new TaskIdParams("non-existent-task"), List.of(), errorHandler); - - // Wait for error to be captured (may come via error handler for streaming) - boolean errorReceived = errorLatch.await(10, TimeUnit.SECONDS); - - if (errorReceived) { - // Error came via error handler - Throwable error = errorRef.get(); - assertNotNull(error); - if (error instanceof A2AClientException) { - assertInstanceOf(TaskNotFoundError.class, ((A2AClientException) error).getCause()); - } else { - // Check if it's directly a TaskNotFoundError or walk the cause chain - Throwable cause = error; - boolean foundTaskNotFound = false; - while (cause != null && !foundTaskNotFound) { - if (cause instanceof TaskNotFoundError) { - foundTaskNotFound = true; - } - cause = cause.getCause(); - } - if (!foundTaskNotFound) { - fail("Expected TaskNotFoundError in error chain"); - } - } - } else { - fail("Expected error for non-existent task resubscription"); - } - } catch (A2AClientException e) { - fail("Expected error for non-existent task resubscription"); - } - } - - /** - * Regression test for race condition where MainQueue closed when first ChildQueue closed, - * preventing resubscription. With reference counting, MainQueue stays alive while any - * ChildQueue exists, allowing successful concurrent operations. - * - * This test verifies that: - * 1. Multiple consumers can be active simultaneously - * 2. All consumers receive events while the MainQueue is alive - * 3. MainQueue doesn't close prematurely when earlier operations complete - */ - @Test - @Timeout(value = 1, unit = TimeUnit.MINUTES) - public void testMainQueueReferenceCountingWithMultipleConsumers() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - // 1. Ensure queue exists for the task - ensureQueueForTask(MINIMAL_TASK.id()); - - // 2. First consumer subscribes and receives initial event - CountDownLatch firstConsumerLatch = new CountDownLatch(1); - AtomicReference firstConsumerEvent = new AtomicReference<>(); - AtomicBoolean firstUnexpectedEvent = new AtomicBoolean(false); - AtomicReference firstErrorRef = new AtomicReference<>(); - AtomicBoolean firstReceivedInitialTask = new AtomicBoolean(false); - - BiConsumer firstConsumer = (event, agentCard) -> { - // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent - if (!firstReceivedInitialTask.get()) { - if (event instanceof TaskEvent) { - firstReceivedInitialTask.set(true); - return; - } else { - fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); - } - } - - // Process subsequent events - if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifact) { - firstConsumerEvent.set(artifact); - firstConsumerLatch.countDown(); - } else if (!(event instanceof TaskUpdateEvent)) { - firstUnexpectedEvent.set(true); - } - }; - - Consumer firstErrorHandler = error -> { - if (!isStreamClosedError(error)) { - firstErrorRef.set(error); - } - firstConsumerLatch.countDown(); - }; - - // Wait for first subscription to be established - CountDownLatch firstSubscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> firstSubscriptionLatch.countDown()); - - getClient().subscribeToTask(new TaskIdParams(MINIMAL_TASK.id()), - List.of(firstConsumer), - firstErrorHandler); - - assertTrue(firstSubscriptionLatch.await(15, TimeUnit.SECONDS), "First subscription should be established"); - - // Enqueue first event - TaskArtifactUpdateEvent event1 = TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("artifact-1") - .parts(new TextPart("First artifact")) - .build()) - .build(); - enqueueEventOnServer(event1); - - // Wait for first consumer to receive event - assertTrue(firstConsumerLatch.await(15, TimeUnit.SECONDS), "First consumer should receive event"); - assertFalse(firstUnexpectedEvent.get()); - assertNull(firstErrorRef.get()); - assertNotNull(firstConsumerEvent.get()); - - // Verify we have multiple child queues (ensureQueue + first subscribe) - int childCountBeforeSecond = getChildQueueCount(MINIMAL_TASK.id()); - assertTrue(childCountBeforeSecond >= 2, "Should have at least 2 child queues"); - - // 3. Second consumer subscribes while first is still active - // This simulates the Kafka replication race condition where resubscription happens - // while other consumers are still active. Without reference counting, the MainQueue - // might close when the ensureQueue ChildQueue closes, preventing this resubscription. - CountDownLatch secondConsumerLatch = new CountDownLatch(1); - AtomicReference secondConsumerEvent = new AtomicReference<>(); - AtomicBoolean secondUnexpectedEvent = new AtomicBoolean(false); - AtomicReference secondErrorRef = new AtomicReference<>(); - AtomicBoolean secondReceivedInitialTask = new AtomicBoolean(false); - - BiConsumer secondConsumer = (event, agentCard) -> { - // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent - if (!secondReceivedInitialTask.get()) { - if (event instanceof TaskEvent) { - secondReceivedInitialTask.set(true); - return; - } else { - fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); - } - } - - // Process subsequent events - if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskArtifactUpdateEvent artifact) { - secondConsumerEvent.set(artifact); - secondConsumerLatch.countDown(); - } else if (!(event instanceof TaskUpdateEvent)) { - secondUnexpectedEvent.set(true); - } - }; - - Consumer secondErrorHandler = error -> { - if (!isStreamClosedError(error)) { - secondErrorRef.set(error); - } - secondConsumerLatch.countDown(); - }; - - // Wait for second subscription to be established - CountDownLatch secondSubscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> secondSubscriptionLatch.countDown()); - - // This should succeed with reference counting because MainQueue stays alive - // while first consumer's ChildQueue exists - getClient().subscribeToTask(new TaskIdParams(MINIMAL_TASK.id()), - List.of(secondConsumer), - secondErrorHandler); - - assertTrue(secondSubscriptionLatch.await(15, TimeUnit.SECONDS), "Second subscription should be established"); - - // Verify child queue count increased (now ensureQueue + first + second) - int childCountAfterSecond = getChildQueueCount(MINIMAL_TASK.id()); - assertTrue(childCountAfterSecond > childCountBeforeSecond, - "Child queue count should increase after second resubscription"); - - // 4. Enqueue second event - both consumers should receive it - TaskArtifactUpdateEvent event2 = TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("artifact-2") - .parts(new TextPart("Second artifact")) - .build()) - .build(); - enqueueEventOnServer(event2); - - // Both consumers should receive the event - assertTrue(secondConsumerLatch.await(15, TimeUnit.SECONDS), "Second consumer should receive event"); - assertFalse(secondUnexpectedEvent.get()); - assertNull(secondErrorRef.get(), - "Resubscription should succeed with reference counting (MainQueue stays alive)"); - - TaskArtifactUpdateEvent receivedEvent = secondConsumerEvent.get(); - assertNotNull(receivedEvent); - assertEquals("artifact-2", receivedEvent.artifact().artifactId()); - assertEquals("Second artifact", ((TextPart) receivedEvent.artifact().parts().get(0)).text()); - - } finally { - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - /** - * Wait for the child queue count to reach a specific value. - * Uses polling with sleep intervals, similar to awaitStreamingSubscription(). - * - * @param taskId The task ID - * @param expectedCount The expected child queue count - * @param timeoutMs Timeout in milliseconds - * @return true if count reached expected value within timeout, false otherwise - */ - private boolean waitForChildQueueCountToBe(String taskId, int expectedCount, long timeoutMs) { - long endTime = System.currentTimeMillis() + timeoutMs; - while (System.currentTimeMillis() < endTime) { - if (getChildQueueCount(taskId) == expectedCount) { - return true; - } - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - return false; - } - } - return false; - } - - @Test - public void testListPushNotificationConfigWithConfigId() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() - .url("http://example.com") - .id("config1") - .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() - .url("http://example.com") - .id("config2") - .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); - - try { - ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - assertEquals(2, result.size()); - assertEquals(new TaskPushNotificationConfig(MINIMAL_TASK.id(), notificationConfig1, null), result.configs().get(0)); - assertEquals(new TaskPushNotificationConfig(MINIMAL_TASK.id(), notificationConfig2, null), result.configs().get(1)); - } catch (Exception e) { - fail(); - } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config1"); - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config2"); - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testListPushNotificationConfigWithoutConfigId() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() - .url("http://1.example.com") - .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() - .url("http://2.example.com") - .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); - - // will overwrite the previous one - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); - try { - ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - assertEquals(1, result.size()); - - PushNotificationConfig expectedNotificationConfig = PushNotificationConfig.builder() - .url("http://2.example.com") - .id(MINIMAL_TASK.id()) - .build(); - assertEquals(new TaskPushNotificationConfig(MINIMAL_TASK.id(), expectedNotificationConfig, null), - result.configs().get(0)); - } catch (Exception e) { - fail(); - } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), MINIMAL_TASK.id()); - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testListPushNotificationConfigTaskNotFound() { - try { - ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams("non-existent-task")); - fail(); - } catch (A2AClientException e) { - assertInstanceOf(TaskNotFoundError.class, e.getCause()); - } - } - - @Test - public void testListPushNotificationConfigEmptyList() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - try { - ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - assertEquals(0, result.size()); - } catch (Exception e) { - fail(e.getMessage()); - } finally { - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testDeletePushNotificationConfigWithValidConfigId() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - saveTaskInTaskStore(Task.builder() - .id("task-456") - .contextId("session-xyz") - .status(new TaskStatus(TaskState.TASK_STATE_SUBMITTED)) - .build()); - - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() - .url("http://example.com") - .id("config1") - .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() - .url("http://example.com") - .id("config2") - .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); - savePushNotificationConfigInStore("task-456", notificationConfig1); - - try { - // specify the config ID to delete - getClient().deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "config1")); - - // should now be 1 left - ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - assertEquals(1, result.size()); - - // should remain unchanged, this is a different task - result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams("task-456")); - assertEquals(1, result.size()); - } catch (Exception e) { - fail(e.getMessage()); - } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config1"); - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config2"); - deletePushNotificationConfigInStore("task-456", "config1"); - deleteTaskInTaskStore(MINIMAL_TASK.id()); - deleteTaskInTaskStore("task-456"); - } - } - - @Test - public void testDeletePushNotificationConfigWithNonExistingConfigId() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() - .url("http://example.com") - .id("config1") - .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() - .url("http://example.com") - .id("config2") - .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); - - try { - getClient().deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), "non-existent-config-id")); - - // should remain unchanged - ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - assertEquals(2, result.size()); - } catch (Exception e) { - fail(); - } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config1"); - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), "config2"); - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - public void testDeletePushNotificationConfigTaskNotFound() { - try { - getClient().deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams("non-existent-task", - "non-existent-config-id")); - fail(); - } catch (A2AClientException e) { - assertInstanceOf(TaskNotFoundError.class, e.getCause()); - } - } - - @Test - public void testDeletePushNotificationConfigSetWithoutConfigId() throws Exception { - saveTaskInTaskStore(MINIMAL_TASK); - PushNotificationConfig notificationConfig1 - = PushNotificationConfig.builder() - .url("http://1.example.com") - .build(); - PushNotificationConfig notificationConfig2 - = PushNotificationConfig.builder() - .url("http://2.example.com") - .build(); - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig1); - - // this one will overwrite the previous one - savePushNotificationConfigInStore(MINIMAL_TASK.id(), notificationConfig2); - - try { - getClient().deleteTaskPushNotificationConfigurations( - new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), MINIMAL_TASK.id())); - - // should now be 0 - ListTaskPushNotificationConfigResult result = getClient().listTaskPushNotificationConfigurations( - new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id()), null); - assertEquals(0, result.size()); - } catch (Exception e) { - fail(); - } finally { - deletePushNotificationConfigInStore(MINIMAL_TASK.id(), MINIMAL_TASK.id()); - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - - @Test - @Timeout(value = 1, unit = TimeUnit.MINUTES) - public void testNonBlockingWithMultipleMessages() throws Exception { - String multiEventTaskId = "multi-event-test-" + java.util.UUID.randomUUID(); - try { - // 1. Send first non-blocking message to create task in WORKING state - Message message1 = Message.builder(MESSAGE) - .taskId(multiEventTaskId) - .contextId("test-context") - .parts(new TextPart("First request")) - .build(); - - AtomicReference taskIdRef = new AtomicReference<>(); - CountDownLatch firstTaskLatch = new CountDownLatch(1); - - BiConsumer firstMessageConsumer = (event, agentCard) -> { - if (event instanceof TaskEvent te) { - taskIdRef.set(te.getTask().id()); - firstTaskLatch.countDown(); - } else if (event instanceof TaskUpdateEvent tue && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent status) { - taskIdRef.set(status.taskId()); - firstTaskLatch.countDown(); - } - }; - - // Non-blocking message creates task in WORKING state and returns immediately - // Queue stays open because task is not in final state - getPollingClient().sendMessage(message1, List.of(firstMessageConsumer), null); - - assertTrue(firstTaskLatch.await(10, TimeUnit.SECONDS)); - String taskId = taskIdRef.get(); - assertNotNull(taskId); - assertEquals(multiEventTaskId, taskId); - - // 2. Subscribe to task (queue should still be open) - CountDownLatch resubEventLatch = new CountDownLatch(2); // artifact-2 + completion - List resubReceivedEvents = new CopyOnWriteArrayList<>(); - AtomicBoolean resubUnexpectedEvent = new AtomicBoolean(false); - AtomicReference resubErrorRef = new AtomicReference<>(); - AtomicBoolean resubReceivedInitialTask = new AtomicBoolean(false); - - BiConsumer resubConsumer = (event, agentCard) -> { - // Per A2A spec 3.1.6: ENFORCE that first event is TaskEvent - if (!resubReceivedInitialTask.get()) { - if (event instanceof TaskEvent) { - resubReceivedInitialTask.set(true); - return; - } else { - fail("First event on subscribe MUST be TaskEvent, but was: " + event.getClass().getSimpleName()); - } - } - - // Process subsequent events - if (event instanceof TaskUpdateEvent tue) { - resubReceivedEvents.add(tue.getUpdateEvent()); - resubEventLatch.countDown(); - } else { - resubUnexpectedEvent.set(true); - } - }; - - Consumer resubErrorHandler = error -> { - if (!isStreamClosedError(error)) { - resubErrorRef.set(error); - } - }; - - // Wait for subscription to be active - CountDownLatch subscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); - - getClient().subscribeToTask(new TaskIdParams(taskId), - List.of(resubConsumer), - resubErrorHandler); - - assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS)); - - // CRITICAL SYNCHRONIZATION: Wait for subscribeToTask's EventConsumer polling loop to start - // - // Race condition: awaitStreamingSubscription() only guarantees transport-level subscription - // (Flow.Subscriber.onSubscribe() called), but EventConsumer polling starts asynchronously - // on a separate thread. Without this check, the agent could emit events before any consumer - // is ready to receive them, causing events to be lost. - // - // This stability check waits for the child queue count to match expectedCount for 3 - // consecutive checks (150ms), ensuring the EventConsumer is actively polling and won't - // miss events when the agent executes. - assertTrue(awaitChildQueueCountStable(taskId, 1, 15000), - "subscribeToTask child queue should be created and stable"); - - // 3. Send second streaming message to same taskId - Message message2 = Message.builder(MESSAGE) - .taskId(multiEventTaskId) // Same taskId - .contextId("test-context") - .parts(new TextPart("Second request")) - .build(); - - CountDownLatch streamEventLatch = new CountDownLatch(2); // artifact-2 + completion - List streamReceivedEvents = new CopyOnWriteArrayList<>(); - AtomicBoolean streamUnexpectedEvent = new AtomicBoolean(false); - - BiConsumer streamConsumer = (event, agentCard) -> { - // This consumer is for sendMessage() (not subscribe), so it doesn't get initial TaskEvent - if (event instanceof TaskUpdateEvent tue) { - streamReceivedEvents.add(tue.getUpdateEvent()); - streamEventLatch.countDown(); - } else { - streamUnexpectedEvent.set(true); - } - }; - - // Wait for streaming subscription to be established before sending message - CountDownLatch streamSubscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> streamSubscriptionLatch.countDown()); - - // Streaming message adds artifact-2 and completes task - getClient().sendMessage(message2, List.of(streamConsumer), null); - - // Ensure subscription is established before agent sends events - assertTrue(streamSubscriptionLatch.await(15, TimeUnit.SECONDS), - "Stream subscription should be established"); - - // 4. Verify both consumers received artifact-2 and completion - assertTrue(resubEventLatch.await(15, TimeUnit.SECONDS)); - assertTrue(streamEventLatch.await(15, TimeUnit.SECONDS)); - - assertFalse(resubUnexpectedEvent.get()); - assertFalse(streamUnexpectedEvent.get()); - assertNull(resubErrorRef.get()); - - // Both should have received 2 events: artifact-2 and completion - assertEquals(2, resubReceivedEvents.size()); - assertEquals(2, streamReceivedEvents.size()); - - // Verify resubscription events - long resubArtifactCount = resubReceivedEvents.stream() - .filter(e -> e instanceof TaskArtifactUpdateEvent) - .count(); - assertEquals(1, resubArtifactCount); - - long resubCompletionCount = resubReceivedEvents.stream() - .filter(e -> e instanceof TaskStatusUpdateEvent) - .filter(e -> ((TaskStatusUpdateEvent) e).isFinal()) - .count(); - assertEquals(1, resubCompletionCount); - - // Verify streaming events - long streamArtifactCount = streamReceivedEvents.stream() - .filter(e -> e instanceof TaskArtifactUpdateEvent) - .count(); - assertEquals(1, streamArtifactCount); - - long streamCompletionCount = streamReceivedEvents.stream() - .filter(e -> e instanceof TaskStatusUpdateEvent) - .filter(e -> ((TaskStatusUpdateEvent) e).isFinal()) - .count(); - assertEquals(1, streamCompletionCount); - - // Verify artifact-2 details from resubscription - TaskArtifactUpdateEvent resubArtifact = (TaskArtifactUpdateEvent) resubReceivedEvents.stream() - .filter(e -> e instanceof TaskArtifactUpdateEvent) - .findFirst() - .orElseThrow(); - assertEquals("artifact-2", resubArtifact.artifact().artifactId()); - assertEquals("Second message artifact", - ((TextPart) resubArtifact.artifact().parts().get(0)).text()); - - // Verify artifact-2 details from streaming - TaskArtifactUpdateEvent streamArtifact = (TaskArtifactUpdateEvent) streamReceivedEvents.stream() - .filter(e -> e instanceof TaskArtifactUpdateEvent) - .findFirst() - .orElseThrow(); - assertEquals("artifact-2", streamArtifact.artifact().artifactId()); - assertEquals("Second message artifact", - ((TextPart) streamArtifact.artifact().parts().get(0)).text()); - } finally { - deleteTaskInTaskStore(multiEventTaskId); - } - } - - /** - * Waits for the child queue count to stabilize at the expected value by calling the server's - * test endpoint. This ensures EventConsumer polling loops have started before proceeding. - * - * @param taskId the task ID whose child queues to monitor - * @param expectedCount the expected number of active child queues - * @param timeoutMs maximum time to wait in milliseconds - * @return true if the count stabilized at the expected value, false if timeout occurred - * @throws IOException if the HTTP request fails - * @throws InterruptedException if interrupted while waiting - */ - private boolean awaitChildQueueCountStable(String taskId, int expectedCount, long timeoutMs) throws IOException, InterruptedException { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/queue/awaitChildCountStable/" + - taskId + "/" + expectedCount + "/" + timeoutMs)) - .POST(HttpRequest.BodyPublishers.noBody()) - .build(); - - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(response.statusCode() + ": Awaiting child queue count failed! " + response.body()); - } - return Boolean.parseBoolean(response.body()); - } - - @Test - @Timeout(value = 1, unit = TimeUnit.MINUTES) - public void testInputRequiredWorkflow() throws Exception { - String inputRequiredTaskId = "input-required-test-" + java.util.UUID.randomUUID(); - boolean taskCreated = false; - try { - // 1. Send initial message - AgentExecutor will transition task to INPUT_REQUIRED - Message initialMessage = Message.builder(MESSAGE) - .taskId(inputRequiredTaskId) - .contextId("test-context") - .parts(new TextPart("Initial request")) - .build(); - - CountDownLatch initialLatch = new CountDownLatch(1); - AtomicReference initialState = new AtomicReference<>(); - AtomicBoolean initialUnexpectedEvent = new AtomicBoolean(false); - - BiConsumer initialConsumer = (event, agentCard) -> { - // Idempotency guard: prevent late events from modifying state after latch countdown - if (initialLatch.getCount() == 0) { - return; - } - if (event instanceof TaskEvent te) { - TaskState state = te.getTask().status().state(); - initialState.set(state); - // Only count down when we receive INPUT_REQUIRED, not intermediate states like WORKING - if (state == TaskState.TASK_STATE_INPUT_REQUIRED) { - initialLatch.countDown(); - } - } else { - initialUnexpectedEvent.set(true); - } - }; - - // Send initial message - task will go to INPUT_REQUIRED state - getNonStreamingClient().sendMessage(initialMessage, List.of(initialConsumer), null); - assertTrue(initialLatch.await(10, TimeUnit.SECONDS)); - assertFalse(initialUnexpectedEvent.get()); - assertEquals(TaskState.TASK_STATE_INPUT_REQUIRED, initialState.get()); - taskCreated = true; - - // 2. Send input message - AgentExecutor will complete the task - Message inputMessage = Message.builder(MESSAGE) - .taskId(inputRequiredTaskId) - .contextId("test-context") - .parts(new TextPart("User input")) - .build(); - - CountDownLatch completionLatch = new CountDownLatch(1); - AtomicReference completedState = new AtomicReference<>(); - AtomicBoolean completionUnexpectedEvent = new AtomicBoolean(false); - - BiConsumer completionConsumer = (event, agentCard) -> { - // Idempotency guard: prevent late events from modifying state after latch countdown - if (completionLatch.getCount() == 0) { - return; - } - if (event instanceof TaskEvent te) { - TaskState state = te.getTask().status().state(); - completedState.set(state); - // Only count down when we receive COMPLETED, not intermediate states like WORKING - if (state == TaskState.TASK_STATE_COMPLETED) { - completionLatch.countDown(); - } - } else { - completionUnexpectedEvent.set(true); - } - }; - - // Send input - task will be completed - getNonStreamingClient().sendMessage(inputMessage, List.of(completionConsumer), null); - assertTrue(completionLatch.await(10, TimeUnit.SECONDS)); - assertFalse(completionUnexpectedEvent.get()); - assertEquals(TaskState.TASK_STATE_COMPLETED, completedState.get()); - - } finally { - if (taskCreated) { - deleteTaskInTaskStore(inputRequiredTaskId); - } - } - } - - @Test - public void testMalformedJSONRPCRequest() { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - // missing closing bracket - String malformedRequest = "{\"jsonrpc\": \"2.0\", \"method\": \"message/send\", \"params\": {\"foo\": \"bar\"}"; - A2AErrorResponse response = given() - .contentType(MediaType.APPLICATION_JSON) - .body(malformedRequest) - .when() - .post("/") - .then() - .statusCode(200) - .extract() - .as(A2AErrorResponse.class); - assertNotNull(response.getError()); - assertEquals(new JSONParseError().getCode(), response.getError().getCode()); - } - - @Test - public void testInvalidParamsJSONRPCRequest() { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - String invalidParamsRequest = """ - {"jsonrpc": "2.0", "method": "SendMessage", "params": "not_a_dict", "id": "1"} - """; - testInvalidParams(invalidParamsRequest); - - invalidParamsRequest = """ - {"jsonrpc": "2.0", "method": "SendMessage", "params": {"message": {"parts": "invalid"}}, "id": "1"} - """; - testInvalidParams(invalidParamsRequest); - } - - private void testInvalidParams(String invalidParamsRequest) { - A2AErrorResponse response = given() - .contentType(MediaType.APPLICATION_JSON) - .body(invalidParamsRequest) - .when() - .post("/") - .then() - .statusCode(200) - .extract() - .as(A2AErrorResponse.class); - assertNotNull(response.getError()); - assertEquals(new InvalidParamsError().getCode(), response.getError().getCode()); - assertEquals("1", response.getId().toString()); - } - - @Test - public void testInvalidJSONRPCRequestMissingJsonrpc() { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - String invalidRequest = """ - { - "method": "SendMessage", - "params": {} - } - """; - A2AErrorResponse response = given() - .contentType(MediaType.APPLICATION_JSON) - .body(invalidRequest) - .when() - .post("/") - .then() - .statusCode(200) - .extract() - .as(A2AErrorResponse.class); - assertNotNull(response.getError()); - assertEquals(new InvalidRequestError().getCode(), response.getError().getCode()); - } - - @Test - public void testInvalidJSONRPCRequestMissingMethod() { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - String invalidRequest = """ - {"jsonrpc": "2.0", "params": {}} - """; - A2AErrorResponse response = given() - .contentType(MediaType.APPLICATION_JSON) - .body(invalidRequest) - .when() - .post("/") - .then() - .statusCode(200) - .extract() - .as(A2AErrorResponse.class); - assertNotNull(response.getError()); - assertEquals(new InvalidRequestError().getCode(), response.getError().getCode()); - } - - @Test - public void testInvalidJSONRPCRequestInvalidId() { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - String invalidRequest = """ - {"jsonrpc": "2.0", "method": "SendMessage", "params": {}, "id": {"bad": "type"}} - """; - A2AErrorResponse response = given() - .contentType(MediaType.APPLICATION_JSON) - .body(invalidRequest) - .when() - .post("/") - .then() - .statusCode(200) - .extract() - .as(A2AErrorResponse.class); - assertNotNull(response.getError()); - assertEquals(new InvalidRequestError().getCode(), response.getError().getCode()); - } - - @Test - public void testInvalidJSONRPCRequestNonExistentMethod() { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - String invalidRequest = """ - {"jsonrpc": "2.0", "id":"5", "method" : "nonexistent/method", "params": {}} - """; - A2AErrorResponse response = given() - .contentType(MediaType.APPLICATION_JSON) - .body(invalidRequest) - .when() - .post("/") - .then() - .statusCode(200) - .extract() - .as(A2AErrorResponse.class); - assertNotNull(response.getError()); - assertEquals(new MethodNotFoundError().getCode(), response.getError().getCode()); - } - - @Test - public void testNonStreamingMethodWithAcceptHeader() throws Exception { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - testGetTask(MediaType.APPLICATION_JSON); - } - - @Test - public void testStreamingMethodWithAcceptHeader() throws Exception { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - testSendStreamingMessageWithHttpClient(MediaType.SERVER_SENT_EVENTS); - } - - @Test - public void testStreamingMethodWithoutAcceptHeader() throws Exception { - // skip this test for non-JSONRPC transports - assumeTrue(TransportProtocol.JSONRPC.asString().equals(getTransportProtocol()), - "JSONRPC-specific test"); - - testSendStreamingMessageWithHttpClient(null); - } - - private void testSendStreamingMessageWithHttpClient(String mediaType) throws Exception { - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendStreamingMessageRequest request = new SendStreamingMessageRequest( - "1", new MessageSendParams(message, null, null, "")); - - CompletableFuture>> responseFuture = initialiseStreamingRequest(request, mediaType); - - CountDownLatch latch = new CountDownLatch(1); - AtomicReference errorRef = new AtomicReference<>(); - - responseFuture.thenAccept(response -> { - if (response.statusCode() != 200) { - //errorRef.set(new IllegalStateException("Status code was " + response.statusCode())); - throw new IllegalStateException("Status code was " + response.statusCode()); - } - response.body().forEach(line -> { - try { - SendStreamingMessageResponse jsonResponse = extractJsonResponseFromSseLine(line); - if (jsonResponse != null) { - assertNull(jsonResponse.getError()); - Message messageResponse = (Message) jsonResponse.getResult(); - assertEquals(MESSAGE.messageId(), messageResponse.messageId()); - assertEquals(MESSAGE.role(), messageResponse.role()); - Part part = messageResponse.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("test message", ((TextPart) part).text()); - latch.countDown(); - } - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - }); - }).exceptionally(t -> { - if (!isStreamClosedError(t)) { - errorRef.set(t); - } - latch.countDown(); - return null; - }); - - boolean dataRead = latch.await(20, TimeUnit.SECONDS); - Assertions.assertTrue(dataRead); - Assertions.assertNull(errorRef.get()); - - } - - public void testSendStreamingMessage(boolean createTask) throws Exception { - if (createTask) { - saveTaskInTaskStore(MINIMAL_TASK); - } - try { - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - CountDownLatch latch = new CountDownLatch(1); - AtomicReference receivedMessage = new AtomicReference<>(); - AtomicBoolean wasUnexpectedEvent = new AtomicBoolean(false); - AtomicReference errorRef = new AtomicReference<>(); - - BiConsumer consumer = (event, agentCard) -> { - if (event instanceof MessageEvent messageEvent) { - if (latch.getCount() > 0) { - receivedMessage.set(messageEvent.getMessage()); - latch.countDown(); - } else { - wasUnexpectedEvent.set(true); - } - } else { - wasUnexpectedEvent.set(true); - } - }; - - Consumer errorHandler = error -> { - errorRef.set(error); - latch.countDown(); - }; - - // testing the streaming send message - getClient().sendMessage(message, List.of(consumer), errorHandler); - - assertTrue(latch.await(10, TimeUnit.SECONDS)); - assertFalse(wasUnexpectedEvent.get()); - assertNull(errorRef.get()); - Message messageResponse = receivedMessage.get(); - assertNotNull(messageResponse); - assertEquals(MESSAGE.messageId(), messageResponse.messageId()); - assertEquals(MESSAGE.role(), messageResponse.role()); - Part part = messageResponse.parts().get(0); - assertTrue(part instanceof TextPart); - assertEquals("test message", ((TextPart) part).text()); - } catch (A2AClientException e) { - fail("Unexpected exception during sendMessage: " + e.getMessage(), e); - } finally { - if (createTask) { - deleteTaskInTaskStore(MINIMAL_TASK.id()); - } - } - } - - private CompletableFuture>> initialiseStreamingRequest( - StreamingJSONRPCRequest request, String mediaType) throws Exception { - - // Create the client - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - String body = ""; - if (request instanceof SendStreamingMessageRequest streamingRequest) { - body = JSONRPCUtils.toJsonRPCRequest((String) streamingRequest.getId(), SEND_STREAMING_MESSAGE_METHOD, ProtoUtils.ToProto.sendMessageRequest(streamingRequest.getParams())); - } - - // Create the request - HttpRequest.Builder builder = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/")) - .POST(HttpRequest.BodyPublishers.ofString(body)) - .header("Content-Type", APPLICATION_JSON); - if (mediaType != null) { - builder.header("Accept", mediaType); - } - HttpRequest httpRequest = builder.build(); - - // Send request async and return the CompletableFuture - return client.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofLines()); - } - - private SendStreamingMessageResponse extractJsonResponseFromSseLine(String line) throws JsonProcessingException { - line = extractSseData(line); - if (line != null) { - return new SendStreamingMessageResponse("", ProtoUtils.FromProto.streamingEventKind(JSONRPCUtils.parseResponseEvent(line))); - } - return null; - } - - private static String extractSseData(String line) { - if (line.startsWith("data:")) { - line = line.substring(5).trim(); - return line; - } - return null; - } - - protected boolean isStreamClosedError(Throwable throwable) { - // Unwrap the CompletionException - Throwable cause = throwable; - - while (cause != null) { - if (cause instanceof EOFException) { - return true; - } - if (cause instanceof IOException && cause.getMessage() != null - && cause.getMessage().contains("cancelled")) { - // stream is closed upon cancellation - return true; - } - cause = cause.getCause(); - } - return false; - } - - protected void saveTaskInTaskStore(Task task) throws Exception { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/task")) - .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(task))) - .header("Content-Type", APPLICATION_JSON) - .build(); - - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(String.format("Saving task failed! Status: %d, Body: %s", response.statusCode(), response.body())); - } - } - - protected Task getTaskFromTaskStore(String taskId) throws Exception { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) - .GET() - .build(); - - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() == 404) { - return null; - } - if (response.statusCode() != 200) { - throw new RuntimeException(String.format("Getting task failed! Status: %d, Body: %s", response.statusCode(), response.body())); - } - return JsonUtil.fromJson(response.body(), Task.class); - } - - protected void deleteTaskInTaskStore(String taskId) throws Exception { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(("http://localhost:" + serverPort + "/test/task/" + taskId))) - .DELETE() - .build(); - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(response.statusCode() + ": Deleting task failed!" + response.body()); - } - } - - protected void ensureQueueForTask(String taskId) throws Exception { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/queue/ensure/" + taskId)) - .POST(HttpRequest.BodyPublishers.noBody()) - .build(); - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(String.format("Ensuring queue failed! Status: %d, Body: %s", response.statusCode(), response.body())); - } - } - - protected void enqueueEventOnServer(Event event) throws Exception { - String path; - if (event instanceof TaskArtifactUpdateEvent e) { - path = "test/queue/enqueueTaskArtifactUpdateEvent/" + e.taskId(); - } else if (event instanceof TaskStatusUpdateEvent e) { - path = "test/queue/enqueueTaskStatusUpdateEvent/" + e.taskId(); - } else { - throw new RuntimeException("Unknown event type " + event.getClass() + ". If you need the ability to" - + " handle more types, please add the REST endpoints."); - } - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/" + path)) - .header("Content-Type", APPLICATION_JSON) - .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(event))) - .build(); - - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(response.statusCode() + ": Queueing event failed!" + response.body()); - } - } - - private CompletableFuture awaitStreamingSubscription() { - int cnt = getStreamingSubscribedCount(); - AtomicInteger initialCount = new AtomicInteger(cnt); - - return CompletableFuture.runAsync(() -> { - try { - boolean done = false; - long end = System.currentTimeMillis() + 15000; - while (System.currentTimeMillis() < end) { - int count = getStreamingSubscribedCount(); - if (count > initialCount.get()) { - done = true; - break; - } - Thread.sleep(500); - } - if (!done) { - throw new RuntimeException("Timed out waiting for subscription"); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Interrupted"); - } - }); - } - - private int getStreamingSubscribedCount() { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/streamingSubscribedCount")) - .GET() - .build(); - try { - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - String body = response.body().trim(); - return Integer.parseInt(body); - } catch (IOException | InterruptedException e) { - throw new RuntimeException(e); - } - } - - protected int getChildQueueCount(String taskId) { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/queue/childCount/" + taskId)) - .GET() - .build(); - try { - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - String body = response.body().trim(); - return Integer.parseInt(body); - } catch (IOException | InterruptedException e) { - throw new RuntimeException(e); - } - } - - protected void deletePushNotificationConfigInStore(String taskId, String configId) throws Exception { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(("http://localhost:" + serverPort + "/test/task/" + taskId + "/config/" + configId))) - .DELETE() - .build(); - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(response.statusCode() + ": Deleting task failed!" + response.body()); - } - } - - protected void savePushNotificationConfigInStore(String taskId, PushNotificationConfig notificationConfig) throws Exception { - HttpClient client = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("http://localhost:" + serverPort + "/test/task/" + taskId)) - .POST(HttpRequest.BodyPublishers.ofString(JsonUtil.toJson(notificationConfig))) - .header("Content-Type", APPLICATION_JSON) - .build(); - - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); - if (response.statusCode() != 200) { - throw new RuntimeException(response.statusCode() + ": Creating task push notification config failed! " + response.body()); - } - } - - /** - * Get a client instance. - */ - protected Client getClient() throws A2AClientException { - if (client == null) { - client = createClient(true); - } - return client; - } - - /** - * Get a client configured for non-streaming operations. - */ - protected Client getNonStreamingClient() throws A2AClientException { - if (nonStreamingClient == null) { - nonStreamingClient = createClient(false); - } - return nonStreamingClient; - } - - /** - * Get a client configured for polling (non-blocking) operations. - */ - protected Client getPollingClient() throws A2AClientException { - if (pollingClient == null) { - pollingClient = createPollingClient(); - } - return pollingClient; - } - - /** - * Create a client with the specified streaming configuration. - */ - private Client createClient(boolean streaming) throws A2AClientException { - AgentCard agentCard = createTestAgentCard(); - ClientConfig clientConfig = createClientConfig(streaming); - - ClientBuilder clientBuilder = Client - .builder(agentCard) - .clientConfig(clientConfig); - - configureTransport(clientBuilder); - - return clientBuilder.build(); - } - - /** - * Create a test agent card with the appropriate transport configuration. - */ - private AgentCard createTestAgentCard() { - return AgentCard.builder() - .name("test-card") - .description("A test agent card") - .version("1.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .supportedInterfaces(List.of(new AgentInterface(getTransportProtocol(), getTransportUrl()))) - .build(); - } - - /** - * Create client configuration with transport-specific settings. - */ - private ClientConfig createClientConfig(boolean streaming) { - return new ClientConfig.Builder() - .setStreaming(streaming) - .build(); - } - - /** - * Create a client configured for polling (non-blocking) operations. - */ - private Client createPollingClient() throws A2AClientException { - AgentCard agentCard = createTestAgentCard(); - ClientConfig clientConfig = new ClientConfig.Builder() - .setStreaming(false) // Non-streaming - .setPolling(true) // Polling mode (translates to blocking=false on server) - .build(); - - ClientBuilder clientBuilder = Client - .builder(agentCard) - .clientConfig(clientConfig); - - configureTransport(clientBuilder); - - return clientBuilder.build(); - } - - /** - * Integration test for THE BIG IDEA: MainQueue stays open for non-final tasks, - * enabling fire-and-forget patterns and late resubscription. - * - * Flow: - * 1. Agent emits WORKING state (non-final) and finishes without completing - * 2. Client disconnects (ChildQueue closes) - * 3. MainQueue should stay OPEN because task is non-final - * 4. Late resubscription should succeed - */ - @Test - @Timeout(value = 2, unit = TimeUnit.MINUTES) - public void testMainQueueStaysOpenForNonFinalTasks() throws Exception { - String taskId = "fire-and-forget-task-integration"; - String contextId = "fire-ctx"; - - // Create task in WORKING state (non-final) - Task workingTask = Task.builder() - .id(taskId) - .contextId(contextId) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - saveTaskInTaskStore(workingTask); - - try { - // Ensure queue exists for the task - ensureQueueForTask(taskId); - - // Send a message that will leave task in WORKING state (fire-and-forget pattern) - Message message = Message.builder(MESSAGE) - .taskId(taskId) - .contextId(contextId) - .parts(new TextPart("fire and forget")) - .build(); - - CountDownLatch firstEventLatch = new CountDownLatch(1); - AtomicReference errorRef = new AtomicReference<>(); - - BiConsumer consumer = (event, agentCard) -> { - // Receive any event (Message) to know agent processed the request - if (event instanceof MessageEvent) { - firstEventLatch.countDown(); - } - }; - - Consumer errorHandler = error -> { - if (!isStreamClosedError(error)) { - errorRef.set(error); - } - firstEventLatch.countDown(); - }; - - // Start streaming subscription - CountDownLatch subscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> subscriptionLatch.countDown()); - - getClient().sendMessage(message, List.of(consumer), errorHandler); - - // Wait for subscription to be established - assertTrue(subscriptionLatch.await(15, TimeUnit.SECONDS), - "Subscription should be established"); - - // Wait for agent to respond (test agent sends Message, not WORKING status) - assertTrue(firstEventLatch.await(15, TimeUnit.SECONDS), - "Should receive agent response"); - assertNull(errorRef.get()); - - // Give agent time to finish (task remains in WORKING state - non-final) - Thread.sleep(2000); - - // THE BIG IDEA TEST: Subscribe to the task - // Even though the agent finished and original ChildQueue closed, - // MainQueue should still be open because task is in non-final WORKING state - CountDownLatch resubLatch = new CountDownLatch(1); - AtomicReference resubErrorRef = new AtomicReference<>(); - - BiConsumer resubConsumer = (event, agentCard) -> { - // We might not receive events immediately, but subscription should succeed - resubLatch.countDown(); - }; - - Consumer resubErrorHandler = error -> { - if (!isStreamClosedError(error)) { - resubErrorRef.set(error); - } - resubLatch.countDown(); - }; - - // This should succeed - MainQueue is still open for non-final task - CountDownLatch resubSubscriptionLatch = new CountDownLatch(1); - awaitStreamingSubscription() - .whenComplete((unused, throwable) -> resubSubscriptionLatch.countDown()); - - getClient().subscribeToTask(new TaskIdParams(taskId), - List.of(resubConsumer), - resubErrorHandler); - - // Wait for resubscription to be established - assertTrue(resubSubscriptionLatch.await(15, TimeUnit.SECONDS), - "Resubscription should succeed - MainQueue stayed open for non-final task"); - - // Verify no errors during resubscription - assertNull(resubErrorRef.get(), - "Resubscription should not error - validates THE BIG IDEA works end-to-end"); - - } finally { - deleteTaskInTaskStore(taskId); - } - } - - /** - * Integration test verifying MainQueue DOES close when task is finalized. - * This ensures Level 2 protection doesn't prevent cleanup of completed tasks. - * - * Flow: - * 1. Send message to new task (creates task in WORKING, then completes it) - * 2. Task reaches COMPLETED state (final) - * 3. ChildQueue closes after receiving final event - * 4. MainQueue should close because task is finalized - * 5. Resubscription should fail with TaskNotFoundError - */ - @Test - @Timeout(value = 2, unit = TimeUnit.MINUTES) - public void testMainQueueClosesForFinalizedTasks() throws Exception { - String taskId = "completed-task-integration"; - String contextId = "completed-ctx"; - - // Send a message that will create and complete the task - Message message = Message.builder(MESSAGE) - .taskId(taskId) - .contextId(contextId) - .parts(new TextPart("complete task")) - .build(); - - CountDownLatch completionLatch = new CountDownLatch(1); - AtomicReference errorRef = new AtomicReference<>(); - - BiConsumer consumer = (event, agentCard) -> { - if (event instanceof TaskEvent te) { - // Might get Task with final state - if (te.getTask().status().state().isFinal()) { - completionLatch.countDown(); - } - } else if (event instanceof MessageEvent me) { - // Message is considered a final event - completionLatch.countDown(); - } else if (event instanceof TaskUpdateEvent tue - && tue.getUpdateEvent() instanceof TaskStatusUpdateEvent status) { - if (status.isFinal()) { - completionLatch.countDown(); - } - } - }; - - Consumer errorHandler = error -> { - if (!isStreamClosedError(error)) { - errorRef.set(error); - } - completionLatch.countDown(); - }; - - try { - // Send message and wait for completion - getClient().sendMessage(message, List.of(consumer), errorHandler); - - assertTrue(completionLatch.await(15, TimeUnit.SECONDS), - "Should receive final event"); - assertNull(errorRef.get(), "Should not have errors during message send"); - - // Give cleanup time to run after final event - Thread.sleep(2000); - - // Try to subscribe to finalized task - should fail - CountDownLatch errorLatch = new CountDownLatch(1); - AtomicReference resubErrorRef = new AtomicReference<>(); - - Consumer resubErrorHandler = error -> { - if (error == null) { - // Stream completed successfully - ignore, we're waiting for an error - return; - } - if (!isStreamClosedError(error)) { - resubErrorRef.set(error); - } - errorLatch.countDown(); - }; - - // Attempt resubscription - try { - getClient().subscribeToTask(new TaskIdParams(taskId), - List.of(), - resubErrorHandler); - - // Wait for error - assertTrue(errorLatch.await(15, TimeUnit.SECONDS), - "Should receive error for finalized task"); - - Throwable error = resubErrorRef.get(); - assertNotNull(error, "Resubscription should fail for finalized task"); - - // Verify it's a TaskNotFoundError - Throwable cause = error; - boolean foundTaskNotFound = false; - while (cause != null && !foundTaskNotFound) { - if (cause instanceof TaskNotFoundError - || (cause instanceof A2AClientException - && ((A2AClientException) cause).getCause() instanceof TaskNotFoundError)) { - foundTaskNotFound = true; - } - cause = cause.getCause(); - } - assertTrue(foundTaskNotFound, - "Should receive TaskNotFoundError - MainQueue closed for finalized task"); - - } catch (A2AClientException e) { - // Exception might be thrown immediately instead of via error handler - assertInstanceOf(TaskNotFoundError.class, e.getCause(), - "Should fail with TaskNotFoundError - MainQueue cleaned up for finalized task"); - } - - } finally { - // Task might not exist in store if created via message send - try { - Task task = getTaskFromTaskStore(taskId); - if (task != null) { - deleteTaskInTaskStore(taskId); - } - } catch (Exception e) { - // Ignore cleanup errors - task might not have been persisted - } - } - } - - /** - * Test agent-to-agent communication with delegation pattern. - *

      - * Verifies that an AgentExecutor can use a client to delegate work to another agent - * by using the "delegate:" prefix. The delegated request is forwarded to another agent - * on the same server, and the artifacts from the delegated task are extracted and returned. - *

      - * This test verifies: - *

        - *
      • Transport type is correctly passed via ServerCallContext state
      • - *
      • AgentExecutor can create a client with matching transport
      • - *
      • Delegation pattern ("delegate:" prefix) is recognized
      • - *
      • Client successfully communicates with same server
      • - *
      • Artifacts from delegated task are extracted and returned
      • - *
      • Original task ID is preserved (not replaced by delegated task ID)
      • - *
      - */ - @Test - public void testAgentToAgentDelegation() throws Exception { - String delegationTaskId = "agent-to-agent-test-" + UUID.randomUUID(); - - Message delegationMessage = Message.builder() - .taskId(delegationTaskId) - .contextId("agent-to-agent-context") - .role(Message.Role.ROLE_USER) - .parts(new TextPart("delegate:What is 2+2?")) - .build(); - - CountDownLatch delegationLatch = new CountDownLatch(1); - AtomicReference delegationResultRef = new AtomicReference<>(); - AtomicReference delegationErrorRef = new AtomicReference<>(); - - BiConsumer delegationConsumer = - AgentToAgentClientFactory.createTaskCaptureConsumer(delegationResultRef, delegationLatch); - - getNonStreamingClient().sendMessage(delegationMessage, List.of(delegationConsumer), error -> { - delegationErrorRef.set(error); - delegationLatch.countDown(); - }); - - assertTrue(delegationLatch.await(30, TimeUnit.SECONDS), "Delegation should complete within timeout"); - - Task delegationResult = delegationResultRef.get(); - - // Only fail on errors if we didn't get a successful result - // (errors can occur after completion due to stream cleanup) - if (delegationResult == null && delegationErrorRef.get() != null) { - fail("Delegation failed: " + delegationErrorRef.get().getMessage()); - } - - assertNotNull(delegationResult, "Delegation task should not be null"); - assertEquals(TaskState.TASK_STATE_COMPLETED, delegationResult.status().state(), - "Delegation task should be completed"); - assertNotNull(delegationResult.artifacts(), "Delegation should have artifacts"); - assertFalse(delegationResult.artifacts().isEmpty(), "Delegation should have at least one artifact"); - - // Extract text from result - String delegatedText = extractTextFromTask(delegationResult); - assertTrue(delegatedText.contains("Handled locally:"), - "Delegated content should have been handled locally by target agent. Got: " + delegatedText); - - // Verify the task ID is the original one (not the delegated task's ID) - assertEquals(delegationTaskId, delegationResult.id(), - "Task ID should be the original task ID, not the delegated task's ID"); - } - - /** - * Test agent-to-agent communication with local handling (no delegation). - *

      - * Verifies that requests without the "delegate:" prefix are handled locally - * by the agent without creating a client connection. - *

      - * This test verifies: - *

        - *
      • Requests without "delegate:" prefix are handled locally
      • - *
      • No client-to-client communication occurs for local handling
      • - *
      • Task completes successfully with expected content
      • - *
      - */ - @Test - public void testAgentToAgentLocalHandling() throws Exception { - String localTaskId = "agent-to-agent-test-" + UUID.randomUUID(); - - Message localMessage = Message.builder() - .taskId(localTaskId) - .contextId("agent-to-agent-context") - .role(Message.Role.ROLE_USER) - .parts(new TextPart("Hello directly")) - .build(); - - CountDownLatch localLatch = new CountDownLatch(1); - AtomicReference localResultRef = new AtomicReference<>(); - AtomicReference localErrorRef = new AtomicReference<>(); - - BiConsumer localConsumer = - AgentToAgentClientFactory.createTaskCaptureConsumer(localResultRef, localLatch); - - getClient().sendMessage(localMessage, List.of(localConsumer), error -> { - localErrorRef.set(error); - localLatch.countDown(); - }); - - assertTrue(localLatch.await(30, TimeUnit.SECONDS), "Local handling should complete within timeout"); - - Task localResult = localResultRef.get(); - - // Only fail on errors if we didn't get a successful result - // (errors can occur after completion due to stream cleanup) - if (localResult == null && localErrorRef.get() != null) { - fail("Local handling failed: " + localErrorRef.get().getMessage()); - } - - assertNotNull(localResult, "Local task should not be null"); - assertEquals(TaskState.TASK_STATE_COMPLETED, localResult.status().state(), - "Local task should be completed"); - - String localText = extractTextFromTask(localResult); - assertTrue(localText.contains("Handled locally: Hello directly"), - "Should be handled locally without delegation. Got: " + localText); - } - - /** - * Extracts all text from a task's artifacts. - * - * @param task the task containing artifacts - * @return concatenated text from all TextParts in all artifacts - */ - private String extractTextFromTask(Task task) { - if (task.artifacts() == null || task.artifacts().isEmpty()) { - return ""; - } - return task.artifacts().stream() - .flatMap(artifact -> artifact.parts().stream()) - .filter(part -> part instanceof TextPart) - .map(part -> ((TextPart) part).text()) - .collect(Collectors.joining("\n")); - } - -} diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java deleted file mode 100644 index 06cdb17f6..000000000 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentCardProducer.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.a2a.server.apps.common; - -import static io.a2a.spec.TransportProtocol.GRPC; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Properties; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; - -import io.a2a.server.ExtendedAgentCard; -import io.a2a.server.PublicAgentCard; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; - -import io.quarkus.arc.profile.IfBuildProfile; -import org.junit.jupiter.api.Assertions; - -@ApplicationScoped -@IfBuildProfile("test") -public class AgentCardProducer { - - private static final String PREFERRED_TRANSPORT = "preferred-transport"; - private static final String A2A_REQUESTHANDLER_TEST_PROPERTIES = "/a2a-requesthandler-test.properties"; - - @Produces - @PublicAgentCard - @ExtendedAgentCard - public AgentCard agentCard() { - String port = System.getProperty("test.agent.card.port", "8081"); - String preferredTransport = loadPreferredTransportFromProperties(); - String transportUrl = GRPC.toString().equals(preferredTransport) ? "localhost:" + port : "http://localhost:" + port; - - AgentCard.Builder builder = AgentCard.builder() - .name("test-card") - .description("A test agent card") - .version("1.0") - .documentationUrl("http://example.com/docs") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extendedAgentCard(true) - .build()) - .defaultInputModes(Collections.singletonList("text")) - .defaultOutputModes(Collections.singletonList("text")) - .skills(new ArrayList<>()) - .supportedInterfaces(Collections.singletonList(new AgentInterface(preferredTransport, transportUrl))); - return builder.build(); - } - - private static String loadPreferredTransportFromProperties() { - URL url = AgentCardProducer.class.getResource(A2A_REQUESTHANDLER_TEST_PROPERTIES); - if (url == null) { - return null; - } - Properties properties = new Properties(); - try { - try (InputStream in = url.openStream()){ - properties.load(in); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - - String preferredTransport = properties.getProperty(PREFERRED_TRANSPORT); - Assertions.assertNotNull(preferredTransport); - return preferredTransport; - } -} - diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java deleted file mode 100644 index 1db5f2d78..000000000 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java +++ /dev/null @@ -1,278 +0,0 @@ -package io.a2a.server.apps.common; - -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; - -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; - -import io.a2a.A2A; -import io.a2a.client.Client; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.ServerCallContext; -import io.a2a.server.agentexecution.AgentExecutor; -import io.a2a.server.agentexecution.RequestContext; -import io.a2a.server.tasks.AgentEmitter; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Artifact; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.Task; -import io.a2a.spec.TextPart; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.UnsupportedOperationError; -import io.quarkus.arc.profile.IfBuildProfile; - -@ApplicationScoped -@IfBuildProfile("test") -public class AgentExecutorProducer { - - // Inject the existing AgentCard to avoid special handling for grpc - @Inject - @PublicAgentCard - AgentCard agentCard; - - @Produces - public AgentExecutor agentExecutor() { - return new AgentExecutor() { - @Override - public void execute(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - String taskId = context.getTaskId(); - - // Agent-to-agent communication test - if (taskId != null && taskId.startsWith("agent-to-agent-test")) { - handleAgentToAgentTest(context, agentEmitter); - return; - } - - // Special handling for multi-event test - if (taskId != null && taskId.startsWith("multi-event-test")) { - // First call: context.getTask() == null (new task) - if (context.getTask() == null) { - agentEmitter.startWork(); - // Return immediately - queue stays open because task is in WORKING state - return; - } else { - // Second call: context.getTask() != null (existing task) - agentEmitter.addArtifact( - List.of(new TextPart("Second message artifact")), - "artifact-2", "Second Artifact", null); - agentEmitter.complete(); - return; - } - } - - // Special handling for input-required test - if (taskId != null && taskId.startsWith("input-required-test")) { - // First call: context.getTask() == null (new task) - if (context.getTask() == null) { - // Go directly to INPUT_REQUIRED without intermediate WORKING state - // This avoids race condition where blocking call interrupts on WORKING - // before INPUT_REQUIRED is persisted to TaskStore - agentEmitter.requiresInput(agentEmitter.newAgentMessage( - List.of(new TextPart("Please provide additional information")), - context.getMessage().metadata())); - // Return immediately - queue stays open because task is in INPUT_REQUIRED state - return; - } else { - String input = extractTextFromMessage(context.getMessage()); - if(! "User input".equals(input)) { - throw new InvalidParamsError("We didn't get the expected input"); - } - // Second call: context.getTask() != null (input provided) - // Go directly to COMPLETED without intermediate WORKING state - // This avoids the same race condition as the first call - agentEmitter.complete(); - return; - } - } - - if (context.getTaskId().equals("task-not-supported-123")) { - throw new UnsupportedOperationError(); - } - - // Check for delegated agent-to-agent messages (marked with special prefix) - if (context.getMessage() != null) { - String userInput = extractTextFromMessage(context.getMessage()); - if (userInput.startsWith("#a2a-delegated#")) { - // This is a delegated message from agent-to-agent test - complete it - String actualContent = userInput.substring("#a2a-delegated#".length()); - agentEmitter.startWork(); - String response = "Handled locally: " + actualContent; - agentEmitter.addArtifact(List.of(new TextPart(response))); - agentEmitter.complete(); - return; - } - } - - // Default handler: echo back message or task - if (context.getMessage() != null) { - agentEmitter.sendMessage(context.getMessage()); - } else { - agentEmitter.addTask(context.getTask()); - } - } - - @Override - public void cancel(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - if (context.getTask().id().equals("cancel-task-123")) { - agentEmitter.cancel(); - } else if (context.getTask().id().equals("cancel-task-not-supported-123")) { - throw new UnsupportedOperationError(); - } - } - - /** - * Handles agent-to-agent communication testing. - * Detects "delegate:" prefix and forwards requests to another agent via client. - */ - private void handleAgentToAgentTest(RequestContext context, AgentEmitter agentEmitter) throws A2AError { - try { - // Get transport protocol from ServerCallContext - ServerCallContext callContext = context.getCallContext(); - if (callContext == null) { - agentEmitter.fail(new InternalError("No call context available for agent-to-agent test")); - return; - } - - TransportProtocol transportProtocol = (TransportProtocol) callContext.getState().get(TRANSPORT_KEY); - if (transportProtocol == null) { - agentEmitter.fail(new InternalError("Transport type not set in call context")); - return; - } - - // Extract user message - String userInput = context.getUserInput("\n"); - if (userInput == null || userInput.isEmpty()) { - agentEmitter.fail(new InternalError("No user input received")); - return; - } - - // Check for delegation pattern - if (userInput.startsWith("delegate:")) { - handleDelegation(userInput, transportProtocol, agentEmitter); - } else { - handleLocally(userInput, agentEmitter); - } - } catch (Exception e) { - // Log the full stack trace to help debug intermittent failures - e.printStackTrace(); - agentEmitter.fail(new InternalError("Agent-to-agent test failed: " + e.getMessage())); - } - } - - /** - * Handles delegation by forwarding to another agent via client. - *

      - * Uses blocking client call (streaming=false) which should return the final task state - * synchronously without requiring async callbacks and latches. This simplified approach - * avoids race conditions between event consumption and callback invocation. - */ - private void handleDelegation(String userInput, TransportProtocol transportProtocol, - AgentEmitter agentEmitter) { - // Strip "delegate:" prefix - String delegatedContent = userInput.substring("delegate:".length()).trim(); - - // Create client for same transport (streaming=false for blocking behavior) - try (Client client = AgentToAgentClientFactory.createClient(agentCard, transportProtocol)) { - agentEmitter.startWork(); - - // Store the result task from blocking call - AtomicReference taskRef = new AtomicReference<>(); - - // Delegate to another agent (new task on same server) - // Add a marker so the receiving agent knows to complete the task - Message delegatedMessage = A2A.toUserMessage("#a2a-delegated#" + delegatedContent); - - // Blocking call should return final task synchronously - client.sendMessage(delegatedMessage, List.of((event, card) -> { - if (event instanceof TaskEvent te) { - taskRef.set(te.getTask()); - } else if (event instanceof TaskUpdateEvent tue) { - taskRef.set(tue.getTask()); - } - }), null); - - // Blocking call should have completed before returning - Task delegatedResult = taskRef.get(); - - if (delegatedResult == null) { - agentEmitter.fail(new InternalError("No result received from blocking delegation call")); - return; - } - - // DIAGNOSTIC: Check if task is actually final - // If blocking call returns non-final task, it indicates a server-side race condition - if (!delegatedResult.status().state().isFinal()) { - String diagnostic = String.format( - "RACE CONDITION DETECTED: Blocking call returned non-final task! " + - "State: %s, TaskId: %s, Artifacts: %d. " + - "This indicates DefaultRequestHandler wait logic failed to synchronize with MainEventBusProcessor.", - delegatedResult.status().state(), - delegatedResult.id(), - delegatedResult.artifacts() != null ? delegatedResult.artifacts().size() : 0); - System.err.println(diagnostic); // Also print to stderr for CI visibility - agentEmitter.fail(new InternalError(diagnostic)); - return; - } - - // Extract artifacts from delegated task and add to current task - // NOTE: We cannot use emitter.addTask(delegatedResult) because it has a different taskId - if (delegatedResult.artifacts() != null && !delegatedResult.artifacts().isEmpty()) { - for (Artifact artifact : delegatedResult.artifacts()) { - agentEmitter.addArtifact(artifact.parts()); - } - } - - // Complete current task - agentEmitter.complete(); - } catch (A2AClientException e) { - agentEmitter.fail(new InternalError("Failed to create client: " + e.getMessage())); - } - } - - /** - * Handles request locally without delegation. - */ - private void handleLocally(String userInput, AgentEmitter agentEmitter) { - try { - agentEmitter.startWork(); - String response = "Handled locally: " + userInput; - agentEmitter.addArtifact(List.of(new TextPart(response))); - agentEmitter.complete(); - } catch (Exception e) { - // Defensive catch to ensure we always emit a final state - e.printStackTrace(); - agentEmitter.fail(new InternalError("Local handling failed: " + e.getMessage())); - } - } - }; - } - - /** - * Extract the content of TextPart in a message to create a single String. - * @param message the message containing the TextPart. - * @return a String aggreagating all the TextPart contents of the message. - */ - private String extractTextFromMessage(final Message message) { - final StringBuilder textBuilder = new StringBuilder(); - if (message.parts() != null) { - for (final Part part : message.parts()) { - if (part instanceof TextPart textPart) { - textBuilder.append(textPart.text()); - } - } - } - return textBuilder.toString(); - } -} diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java deleted file mode 100644 index f3c06eb66..000000000 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentToAgentClientFactory.java +++ /dev/null @@ -1,119 +0,0 @@ -package io.a2a.server.apps.common; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; - -import io.a2a.client.Client; -import io.a2a.client.ClientBuilder; -import io.a2a.client.ClientEvent; -import io.a2a.client.TaskEvent; -import io.a2a.client.TaskUpdateEvent; -import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.grpc.GrpcTransport; -import io.a2a.client.transport.grpc.GrpcTransportConfigBuilder; -import io.a2a.client.transport.jsonrpc.JSONRPCTransport; -import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; -import io.a2a.client.transport.rest.RestTransport; -import io.a2a.client.transport.rest.RestTransportConfigBuilder; -import io.a2a.spec.A2AClientException; -import io.a2a.spec.AgentCard; -import io.a2a.spec.Task; -import io.a2a.spec.TransportProtocol; -import io.grpc.ManagedChannel; -import io.grpc.ManagedChannelBuilder; - -/** - * Helper class for creating A2A clients for agent-to-agent communication testing. - * Uses inner classes to avoid class loading issues when transport dependencies aren't on the classpath. - */ -public class AgentToAgentClientFactory { - - /** - * Creates a BiConsumer that captures the final task state. - * This utility method is used by both test classes and agent executors to avoid code duplication. - * - * @param taskRef the AtomicReference to store the final task - * @param latch the CountDownLatch to signal completion - * @return a BiConsumer that captures completed tasks - */ - public static BiConsumer createTaskCaptureConsumer( - AtomicReference taskRef, CountDownLatch latch) { - return (event, agentCard) -> { - Task task = null; - if (event instanceof TaskEvent taskEvent) { - task = taskEvent.getTask(); - } else if (event instanceof TaskUpdateEvent taskUpdateEvent) { - task = taskUpdateEvent.getTask(); - } - - if (task != null && task.status().state().isFinal()) { - taskRef.set(task); - latch.countDown(); - } - }; - } - - /** - * Creates a client for the specified transport protocol. - * The agent card parameter already contains the correct local endpoint URLs - * configured by the test's AgentCardProducer. - * - * @param agentCard the agent card with correct local endpoints - * @param transportProtocol the transport protocol to use - * @return configured client - * @throws A2AClientException if client creation fails - */ - public static Client createClient(AgentCard agentCard, TransportProtocol transportProtocol) - throws A2AClientException { - ClientConfig clientConfig = ClientConfig.builder() - .setStreaming(false) - .build(); - - ClientBuilder clientBuilder = Client.builder(agentCard) - .clientConfig(clientConfig); - - ClientTransportEnhancer enhancer = switch (transportProtocol) { - case JSONRPC -> new JsonRpcClientEnhancer(); - case GRPC -> new GrpcClientEnhancer(); - case HTTP_JSON -> new RestClientEnhancer(); - default -> throw new IllegalArgumentException("Unsupported transport: " + transportProtocol); - }; - - enhancer.enhance(clientBuilder); - return clientBuilder.build(); - } - - /** - * The implementations of this interface are needed to avoid ClassNotFoundErrors for client transports that are - * not on the classpath. - */ - interface ClientTransportEnhancer { - void enhance(ClientBuilder clientBuilder); - } - - private static class GrpcClientEnhancer implements AgentToAgentClientFactory.ClientTransportEnhancer { - @Override - public void enhance(ClientBuilder clientBuilder) { - clientBuilder.withTransport(GrpcTransport.class, new GrpcTransportConfigBuilder().channelFactory(target -> { - ManagedChannel channel = ManagedChannelBuilder.forTarget(target).usePlaintext().build(); - return channel; - })); - } - } - - private static class JsonRpcClientEnhancer implements AgentToAgentClientFactory.ClientTransportEnhancer { - @Override - public void enhance(ClientBuilder clientBuilder) { - clientBuilder.withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()); - } - } - - private static class RestClientEnhancer implements AgentToAgentClientFactory.ClientTransportEnhancer { - @Override - public void enhance(ClientBuilder clientBuilder) { - clientBuilder.withTransport(RestTransport.class, new RestTransportConfigBuilder()); - } - } -} - diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java deleted file mode 100644 index 9b8214ed7..000000000 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.a2a.server.apps.common; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.function.Consumer; - -import jakarta.enterprise.context.Dependent; -import jakarta.enterprise.inject.Alternative; - -import io.a2a.client.http.A2AHttpClient; -import io.a2a.client.http.A2AHttpResponse; -import io.a2a.jsonrpc.common.json.JsonProcessingException; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.spec.Task; - -@Dependent -@Alternative -public class TestHttpClient implements A2AHttpClient { - final List tasks = Collections.synchronizedList(new ArrayList<>()); - volatile CountDownLatch latch; - - @Override - public GetBuilder createGet() { - return null; - } - - @Override - public PostBuilder createPost() { - return new TestPostBuilder(); - } - - @Override - public DeleteBuilder createDelete() { - return null; - } - - class TestPostBuilder implements A2AHttpClient.PostBuilder { - private volatile String body; - @Override - public PostBuilder body(String body) { - this.body = body; - return this; - } - - @Override - public A2AHttpResponse post() throws IOException, InterruptedException { - try { - tasks.add(JsonUtil.fromJson(body, Task.class)); - } catch (JsonProcessingException e) { - throw new IOException("Failed to parse task JSON", e); - } - try { - return new A2AHttpResponse() { - @Override - public int status() { - return 200; - } - - @Override - public boolean success() { - return true; - } - - @Override - public String body() { - return ""; - } - }; - } finally { - latch.countDown(); - } - } - - @Override - public CompletableFuture postAsyncSSE(Consumer messageConsumer, Consumer errorConsumer, Runnable completeRunnable) throws IOException, InterruptedException { - return null; - } - - @Override - public PostBuilder url(String s) { - return this; - } - - @Override - public PostBuilder addHeader(String name, String value) { - return this; - } - - @Override - public PostBuilder addHeaders(Map headers) { - return this; - } - } -} \ No newline at end of file diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java deleted file mode 100644 index f94d93043..000000000 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestUtilsBean.java +++ /dev/null @@ -1,113 +0,0 @@ -package io.a2a.server.apps.common; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import io.a2a.server.events.QueueManager; -import io.a2a.server.tasks.PushNotificationConfigStore; -import io.a2a.server.tasks.TaskStore; -import io.a2a.spec.Event; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.Task; - -/** - * Contains utilities to interact with the server side for the tests. - * The intent for this bean is to be exposed via REST. - * - *

      There is a Quarkus implementation in {@code A2ATestRoutes} which shows the contract for how to - * expose it via REST. For other REST frameworks, you will need to provide an implementation that works in a similar - * way to {@code A2ATestRoutes}.

      - */ -@ApplicationScoped -public class TestUtilsBean { - - @Inject - TaskStore taskStore; - - @Inject - QueueManager queueManager; - - @Inject - PushNotificationConfigStore pushNotificationConfigStore; - - public void saveTask(Task task) { - taskStore.save(task, false); - } - - public Task getTask(String taskId) { - return taskStore.get(taskId); - } - - public void deleteTask(String taskId) { - taskStore.delete(taskId); - } - - public void ensureQueue(String taskId) { - queueManager.createOrTap(taskId); - } - - public void enqueueEvent(String taskId, Event event) { - queueManager.get(taskId).enqueueEvent(event); - } - - public int getChildQueueCount(String taskId) { - return queueManager.getActiveChildQueueCount(taskId); - } - - public void deleteTaskPushNotificationConfig(String taskId, String configId) { - pushNotificationConfigStore.deleteInfo(taskId, configId); - } - - public void saveTaskPushNotificationConfig(String taskId, PushNotificationConfig notificationConfig) { - pushNotificationConfigStore.setInfo(taskId, notificationConfig); - } - - /** - * Waits for the EventConsumer polling loop to start for the specified task's queue. - * This ensures the queue is ready to receive and process events. - * - * @param taskId the task ID whose queue poller to wait for - * @throws InterruptedException if interrupted while waiting - */ - public void awaitQueuePollerStart(String taskId) throws InterruptedException { - queueManager.awaitQueuePollerStart(queueManager.get(taskId)); - } - - /** - * Waits for the child queue count to stabilize at the expected value. - *

      - * This method addresses a race condition where EventConsumer polling loops may not have started - * yet when events are emitted. It waits for the child queue count to match the expected value - * for 3 consecutive checks (150ms total), ensuring EventConsumers are actively polling and - * won't miss events. - *

      - * Use this after operations that create child queues (e.g., subscribeToTask, sendMessage) to - * ensure their EventConsumer polling loops have started before the agent emits events. - * - * @param taskId the task ID whose child queues to monitor - * @param expectedCount the expected number of active child queues - * @param timeoutMs maximum time to wait in milliseconds - * @return true if the count stabilized at the expected value, false if timeout occurred - * @throws InterruptedException if interrupted while waiting - */ - public boolean awaitChildQueueCountStable(String taskId, int expectedCount, long timeoutMs) throws InterruptedException { - long endTime = System.currentTimeMillis() + timeoutMs; - int consecutiveMatches = 0; - final int requiredMatches = 3; // Count must match 3 times in a row (150ms) to be considered stable - - while (System.currentTimeMillis() < endTime) { - int count = queueManager.getActiveChildQueueCount(taskId); - if (count == expectedCount) { - consecutiveMatches++; - if (consecutiveMatches >= requiredMatches) { - // Count is stable - all child queues exist and haven't closed - return true; - } - } else { - consecutiveMatches = 0; // Reset if count changes - } - Thread.sleep(50); - } - return false; - } -} diff --git a/tests/server-common/src/test/resources/META-INF/beans.xml b/tests/server-common/src/test/resources/META-INF/beans.xml deleted file mode 100644 index b0e6ff3e2..000000000 --- a/tests/server-common/src/test/resources/META-INF/beans.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml deleted file mode 100644 index a84002823..000000000 --- a/transport/grpc/pom.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-transport-grpc - - jar - - Java SDK A2A Transport: gRPC - Java SDK for the Agent2Agent Protocol (A2A) - gRPC - - - - io.github.a2asdk - a2a-java-sdk-server-common - - - ${project.groupId} - a2a-java-sdk-server-common - test-jar - test - - - ${project.groupId} - a2a-java-sdk-spec-grpc - - - ${project.groupId} - a2a-java-sdk-jsonrpc-common - ${project.version} - - - com.google.protobuf - protobuf-java - - - io.grpc - grpc-protobuf - - - io.grpc - grpc-stub - - - jakarta.enterprise - jakarta.enterprise.cdi-api - - - jakarta.inject - jakarta.inject-api - - - ch.qos.logback - logback-classic - test - - - org.junit.jupiter - junit-jupiter-api - test - - - org.mockito - mockito-core - test - - - io.grpc - grpc-testing - test - - - - - diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java deleted file mode 100644 index a1392f20a..000000000 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/context/GrpcContextKeys.java +++ /dev/null @@ -1,75 +0,0 @@ -package io.a2a.transport.grpc.context; - - -import java.util.Map; - -import io.a2a.spec.A2AMethods; -import io.grpc.Context; - -/** - * Shared gRPC context keys for A2A protocol data. - * - * These keys provide access to gRPC context information similar to - * Python's grpc.aio.ServicerContext, enabling rich context access - * in service method implementations. - */ -public final class GrpcContextKeys { - - /** - * Context key for storing the X-A2A-Version header value. - * Set by server interceptors and accessed by service handlers. - */ - public static final Context.Key VERSION_HEADER_KEY = - Context.key("x-a2a-version"); - - /** - * Context key for storing the X-A2A-Extensions header value. - * Set by server interceptors and accessed by service handlers. - */ - public static final Context.Key EXTENSIONS_HEADER_KEY = - Context.key("x-a2a-extensions"); - - /** - * Context key for storing the complete gRPC Metadata object. - * Provides access to all request headers and metadata. - */ - public static final Context.Key METADATA_KEY = - Context.key("grpc-metadata"); - - /** - * Context key for storing the method name being called. - * Equivalent to Python's context.method() functionality. - */ - public static final Context.Key GRPC_METHOD_NAME_KEY = - Context.key("grpc-method-name"); - - /** - * Context key for storing the method name being called. - * Equivalent to Python's context.method() functionality. - */ - public static final Context.Key METHOD_NAME_KEY = - Context.key("method"); - - /** - * Context key for storing the peer information. - * Provides access to client connection details. - */ - public static final Context.Key PEER_INFO_KEY = - Context.key("grpc-peer-info"); - - public static final Map METHOD_MAPPING = Map.of( - "SendMessage", A2AMethods.SEND_MESSAGE_METHOD, - "SendStreamingMessage", A2AMethods.SEND_STREAMING_MESSAGE_METHOD, - "GetTask", A2AMethods.GET_TASK_METHOD, - "ListTask", A2AMethods.LIST_TASK_METHOD, - "CancelTask", A2AMethods.CANCEL_TASK_METHOD, - "SubscribeToTask", A2AMethods.SUBSCRIBE_TO_TASK_METHOD, - "CreateTaskPushNotification", A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - "GetTaskPushNotification", A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - "ListTaskPushNotification", A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, - "DeleteTaskPushNotification", A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); - - private GrpcContextKeys() { - // Utility class - } -} diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java deleted file mode 100644 index f214a51e5..000000000 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/CallContextFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.a2a.transport.grpc.handler; - -import io.a2a.server.ServerCallContext; -import io.grpc.stub.StreamObserver; - -public interface CallContextFactory { - ServerCallContext create(StreamObserver responseObserver); -} \ No newline at end of file diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java deleted file mode 100644 index 277a763cd..000000000 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java +++ /dev/null @@ -1,676 +0,0 @@ -package io.a2a.transport.grpc.handler; - -import static io.a2a.grpc.utils.ProtoUtils.FromProto; -import static io.a2a.grpc.utils.ProtoUtils.ToProto; -import static io.a2a.server.ServerCallContext.TRANSPORT_KEY; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Logger; - -import jakarta.enterprise.inject.Vetoed; - -import com.google.protobuf.Empty; -import io.a2a.common.A2AErrorMessages; -import io.a2a.grpc.A2AServiceGrpc; -import io.a2a.grpc.StreamResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.AgentCardValidator; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.auth.User; -import io.a2a.server.extensions.A2AExtensions; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.version.A2AVersionValidator; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TransportProtocol; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; -import io.a2a.transport.grpc.context.GrpcContextKeys; -import io.grpc.Context; -import io.grpc.Metadata; -import io.grpc.Status; -import io.grpc.stub.StreamObserver; -import org.jspecify.annotations.Nullable; - -@Vetoed -public abstract class GrpcHandler extends A2AServiceGrpc.A2AServiceImplBase { - - // Hook so testing can wait until streaming subscriptions are established. - // Without this we get intermittent failures - private static volatile @Nullable Runnable streamingSubscribedRunnable; - - private final AtomicBoolean initialised = new AtomicBoolean(false); - - private static final Logger LOGGER = Logger.getLogger(GrpcHandler.class.getName()); - - public GrpcHandler() { - - } - - @Override - public void sendMessage(io.a2a.grpc.SendMessageRequest request, - StreamObserver responseObserver) { - try { - ServerCallContext context = createCallContext(responseObserver); - A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context); - A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context); - MessageSendParams params = FromProto.messageSendParams(request); - EventKind taskOrMessage = getRequestHandler().onMessageSend(params, context); - io.a2a.grpc.SendMessageResponse response = ToProto.taskOrMessage(taskOrMessage); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void getTask(io.a2a.grpc.GetTaskRequest request, - StreamObserver responseObserver) { - try { - ServerCallContext context = createCallContext(responseObserver); - TaskQueryParams params = FromProto.taskQueryParams(request); - Task task = getRequestHandler().onGetTask(params, context); - if (task != null) { - responseObserver.onNext(ToProto.task(task)); - responseObserver.onCompleted(); - } else { - handleError(responseObserver, new TaskNotFoundError()); - } - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void listTasks(io.a2a.grpc.ListTasksRequest request, - StreamObserver responseObserver) { - try { - ServerCallContext context = createCallContext(responseObserver); - io.a2a.spec.ListTasksParams params = FromProto.listTasksParams(request); - ListTasksResult result = getRequestHandler().onListTasks(params, context); - responseObserver.onNext(ToProto.listTasksResult(result)); - responseObserver.onCompleted(); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void cancelTask(io.a2a.grpc.CancelTaskRequest request, - StreamObserver responseObserver) { - try { - ServerCallContext context = createCallContext(responseObserver); - TaskIdParams params = FromProto.taskIdParams(request); - Task task = getRequestHandler().onCancelTask(params, context); - if (task != null) { - responseObserver.onNext(ToProto.task(task)); - responseObserver.onCompleted(); - } else { - handleError(responseObserver, new TaskNotFoundError()); - } - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void createTaskPushNotificationConfig(io.a2a.grpc.CreateTaskPushNotificationConfigRequest request, - StreamObserver responseObserver) { - if (!getAgentCardInternal().capabilities().pushNotifications()) { - handleError(responseObserver, new PushNotificationNotSupportedError()); - return; - } - - try { - ServerCallContext context = createCallContext(responseObserver); - TaskPushNotificationConfig config = FromProto.CreateTaskPushNotificationConfig(request); - TaskPushNotificationConfig responseConfig = getRequestHandler().onCreateTaskPushNotificationConfig(config, context); - responseObserver.onNext(ToProto.taskPushNotificationConfig(responseConfig)); - responseObserver.onCompleted(); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationConfigRequest request, - StreamObserver responseObserver) { - if (!getAgentCardInternal().capabilities().pushNotifications()) { - handleError(responseObserver, new PushNotificationNotSupportedError()); - return; - } - - try { - ServerCallContext context = createCallContext(responseObserver); - GetTaskPushNotificationConfigParams params = FromProto.getTaskPushNotificationConfigParams(request); - TaskPushNotificationConfig config = getRequestHandler().onGetTaskPushNotificationConfig(params, context); - responseObserver.onNext(ToProto.taskPushNotificationConfig(config)); - responseObserver.onCompleted(); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationConfigRequest request, - StreamObserver responseObserver) { - if (!getAgentCardInternal().capabilities().pushNotifications()) { - handleError(responseObserver, new PushNotificationNotSupportedError()); - return; - } - - try { - ServerCallContext context = createCallContext(responseObserver); - ListTaskPushNotificationConfigParams params = FromProto.listTaskPushNotificationConfigParams(request); - ListTaskPushNotificationConfigResult result = getRequestHandler().onListTaskPushNotificationConfig(params, context); - io.a2a.grpc.ListTaskPushNotificationConfigResponse response = ToProto.listTaskPushNotificationConfigResponse(result); - responseObserver.onNext(response); - responseObserver.onCompleted(); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, - StreamObserver responseObserver) { - if (!getAgentCardInternal().capabilities().streaming()) { - handleError(responseObserver, new InvalidRequestError()); - return; - } - - try { - ServerCallContext context = createCallContext(responseObserver); - A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context); - A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context); - MessageSendParams params = FromProto.messageSendParams(request); - Flow.Publisher publisher = getRequestHandler().onMessageSendStream(params, context); - convertToStreamResponse(publisher, responseObserver, context); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, - StreamObserver responseObserver) { - if (!getAgentCardInternal().capabilities().streaming()) { - handleError(responseObserver, new InvalidRequestError()); - return; - } - - try { - ServerCallContext context = createCallContext(responseObserver); - TaskIdParams params = FromProto.taskIdParams(request); - Flow.Publisher publisher = getRequestHandler().onSubscribeToTask(params, context); - convertToStreamResponse(publisher, responseObserver, context); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - private void convertToStreamResponse(Flow.Publisher publisher, - StreamObserver responseObserver, - ServerCallContext context) { - CompletableFuture.runAsync(() -> { - publisher.subscribe(new Flow.Subscriber() { - private Flow.@Nullable Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - if (this.subscription != null) { - this.subscription.request(1); - } - - // Detect gRPC client disconnect and call EventConsumer.cancel() directly - // This stops the polling loop without relying on subscription cancellation propagation - Context grpcContext = Context.current(); - grpcContext.addListener(new Context.CancellationListener() { - @Override - public void cancelled(Context ctx) { - LOGGER.fine(() -> "gRPC call cancelled by client, calling EventConsumer.cancel() to stop polling loop"); - context.invokeEventConsumerCancelCallback(); - subscription.cancel(); - } - }, getExecutor()); - - // Notify tests that we are subscribed - Runnable runnable = streamingSubscribedRunnable; - if (runnable != null) { - runnable.run(); - } - } - - @Override - public void onNext(StreamingEventKind event) { - StreamResponse response = ToProto.streamResponse(event); - responseObserver.onNext(response); - if (response.hasStatusUpdate()) { - io.a2a.grpc.TaskState state = response.getStatusUpdate().getStatus().getState(); - boolean isFinal = state == io.a2a.grpc.TaskState.TASK_STATE_CANCELED - || state == io.a2a.grpc.TaskState.TASK_STATE_COMPLETED - || state == io.a2a.grpc.TaskState.TASK_STATE_FAILED - || state == io.a2a.grpc.TaskState.TASK_STATE_REJECTED; - if (isFinal) { - responseObserver.onCompleted(); - } else { - if (this.subscription != null) { - subscription.request(1); - } - } - } else { - if (this.subscription != null) { - this.subscription.request(1); - } - } - } - - @Override - public void onError(Throwable throwable) { - // Cancel upstream to stop EventConsumer when error occurs - if (this.subscription != null) { - subscription.cancel(); - } - if (throwable instanceof A2AError jsonrpcError) { - handleError(responseObserver, jsonrpcError); - } else { - handleInternalError(responseObserver, throwable); - } - responseObserver.onCompleted(); - } - - @Override - public void onComplete() { - responseObserver.onCompleted(); - } - }); - }, getExecutor()); - } - - @Override - public void getExtendedAgentCard(io.a2a.grpc.GetExtendedAgentCardRequest request, - StreamObserver responseObserver) { - try { - AgentCard extendedAgentCard = getExtendedAgentCard(); - if (extendedAgentCard != null) { - responseObserver.onNext(ToProto.agentCard(extendedAgentCard)); - responseObserver.onCompleted(); - } else { - // Extended agent card not configured - return error instead of hanging - handleError(responseObserver, new ExtendedAgentCardNotConfiguredError(null, "Extended agent card not configured", null)); - } - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - @Override - public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificationConfigRequest request, - StreamObserver responseObserver) { - if (!getAgentCardInternal().capabilities().pushNotifications()) { - handleError(responseObserver, new PushNotificationNotSupportedError()); - return; - } - - try { - ServerCallContext context = createCallContext(responseObserver); - DeleteTaskPushNotificationConfigParams params = FromProto.deleteTaskPushNotificationConfigParams(request); - getRequestHandler().onDeleteTaskPushNotificationConfig(params, context); - // void response - responseObserver.onNext(Empty.getDefaultInstance()); - responseObserver.onCompleted(); - } catch (A2AError e) { - handleError(responseObserver, e); - } catch (SecurityException e) { - handleSecurityException(responseObserver, e); - } catch (Throwable t) { - handleInternalError(responseObserver, t); - } - } - - private ServerCallContext createCallContext(StreamObserver responseObserver) { - CallContextFactory factory = getCallContextFactory(); - if (factory == null) { - // Default implementation when no custom CallContextFactory is provided - // This handles both CDI injection scenarios and test scenarios where callContextFactory is null - User user = UnauthenticatedUser.INSTANCE; - Map state = new HashMap<>(); - state.put(TRANSPORT_KEY, TransportProtocol.GRPC); - - // Enhanced gRPC context access - equivalent to Python's grpc.aio.ServicerContext - // The A2AExtensionsInterceptor captures ServerCall + Metadata and stores them in gRPC Context - // This provides proper equivalence to Python's ServicerContext for metadata access - // Note: StreamObserver is still stored for response handling - state.put("grpc_response_observer", responseObserver); - - // Add rich gRPC context information if available (set by interceptor) - // This provides equivalent functionality to Python's grpc.aio.ServicerContext - try { - Context currentContext = Context.current(); - if (currentContext != null) { - state.put("grpc_context", currentContext); - - // Add specific context information for easy access - io.grpc.Metadata grpcMetadata = GrpcContextKeys.METADATA_KEY.get(currentContext); - if (grpcMetadata != null) { - state.put("grpc_metadata", grpcMetadata); - } - Map headers= new HashMap<>(); - for(String key : grpcMetadata.keys()) { - headers.put(key, grpcMetadata.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER))); - } - state.put("headers", headers); - String methodName = GrpcContextKeys.GRPC_METHOD_NAME_KEY.get(currentContext); - if (methodName != null) { - state.put("grpc_method_name", methodName); - } - - String peerInfo = GrpcContextKeys.PEER_INFO_KEY.get(currentContext); - if (peerInfo != null) { - state.put("grpc_peer_info", peerInfo); - } - } - } catch (Exception e) { - // Context not available - continue without it - LOGGER.fine(() -> "Error getting data from current context" + e); - } - - // Extract requested protocol version from gRPC context (set by interceptor) - String requestedVersion = getVersionFromContext(); - - // Extract requested extensions from gRPC context (set by interceptor) - Set requestedExtensions = new HashSet<>(); - String extensionsHeader = getExtensionsFromContext(); - if (extensionsHeader != null) { - requestedExtensions = A2AExtensions.getRequestedExtensions(List.of(extensionsHeader)); - } - - return new ServerCallContext(user, state, requestedExtensions, requestedVersion); - } else { - // TODO: CallContextFactory interface expects ServerCall + Metadata, but we only have StreamObserver - // This is another manifestation of the architectural limitation mentioned above - return factory.create(responseObserver); // Fall back to basic create() method for now - } - } - - private void handleError(StreamObserver responseObserver, A2AError error) { - Status status; - String description; - if (error instanceof InvalidRequestError) { - status = Status.INVALID_ARGUMENT; - description = "InvalidRequestError: " + error.getMessage(); - } else if (error instanceof MethodNotFoundError) { - status = Status.NOT_FOUND; - description = "MethodNotFoundError: " + error.getMessage(); - } else if (error instanceof InvalidParamsError) { - status = Status.INVALID_ARGUMENT; - description = "InvalidParamsError: " + error.getMessage(); - } else if (error instanceof InternalError) { - status = Status.INTERNAL; - description = "InternalError: " + error.getMessage(); - } else if (error instanceof TaskNotFoundError) { - status = Status.NOT_FOUND; - description = "TaskNotFoundError: " + error.getMessage(); - } else if (error instanceof TaskNotCancelableError) { - status = Status.FAILED_PRECONDITION; - description = "TaskNotCancelableError: " + error.getMessage(); - } else if (error instanceof PushNotificationNotSupportedError) { - status = Status.UNIMPLEMENTED; - description = "PushNotificationNotSupportedError: " + error.getMessage(); - } else if (error instanceof UnsupportedOperationError) { - status = Status.UNIMPLEMENTED; - description = "UnsupportedOperationError: " + error.getMessage(); - } else if (error instanceof JSONParseError) { - status = Status.INTERNAL; - description = "JSONParseError: " + error.getMessage(); - } else if (error instanceof ContentTypeNotSupportedError) { - status = Status.INVALID_ARGUMENT; - description = "ContentTypeNotSupportedError: " + error.getMessage(); - } else if (error instanceof InvalidAgentResponseError) { - status = Status.INTERNAL; - description = "InvalidAgentResponseError: " + error.getMessage(); - } else if (error instanceof ExtendedAgentCardNotConfiguredError) { - status = Status.FAILED_PRECONDITION; - description = "ExtendedCardNotConfiguredError: " + error.getMessage(); - } else if (error instanceof ExtensionSupportRequiredError) { - status = Status.FAILED_PRECONDITION; - description = "ExtensionSupportRequiredError: " + error.getMessage(); - } else if (error instanceof VersionNotSupportedError) { - status = Status.UNIMPLEMENTED; - description = "VersionNotSupportedError: " + error.getMessage(); - } else { - status = Status.UNKNOWN; - description = "Unknown error type: " + error.getMessage(); - } - responseObserver.onError(status.withDescription(description).asRuntimeException()); - } - - private void handleSecurityException(StreamObserver responseObserver, SecurityException e) { - Status status; - String description; - - String exceptionClassName = e.getClass().getName(); - - // Attempt to detect common authentication and authorization related exceptions - if (exceptionClassName.contains("Unauthorized") || - exceptionClassName.contains("Unauthenticated") || - exceptionClassName.contains("Authentication")) { - status = Status.UNAUTHENTICATED; - description = A2AErrorMessages.AUTHENTICATION_FAILED; - } else if (exceptionClassName.contains("Forbidden") || - exceptionClassName.contains("AccessDenied") || - exceptionClassName.contains("Authorization")) { - status = Status.PERMISSION_DENIED; - description = A2AErrorMessages.AUTHORIZATION_FAILED; - } else { - // If the security exception type cannot be detected, default to PERMISSION_DENIED - status = Status.PERMISSION_DENIED; - description = "Authorization failed: " + (e.getMessage() != null ? e.getMessage() : "Access denied"); - } - - responseObserver.onError(status.withDescription(description).asRuntimeException()); - } - - private void handleInternalError(StreamObserver responseObserver, Throwable t) { - handleError(responseObserver, new InternalError(t.getMessage())); - } - - - private AgentCard getAgentCardInternal() { - AgentCard agentCard = getAgentCard(); - if (initialised.compareAndSet(false, true)) { - // Validate transport configuration with proper classloader context - validateTransportConfigurationWithCorrectClassLoader(agentCard); - } - return agentCard; - } - - private void validateTransportConfigurationWithCorrectClassLoader(AgentCard agentCard) { - ClassLoader originalTccl = Thread.currentThread().getContextClassLoader(); - ClassLoader deploymentCl = getDeploymentClassLoader(); - boolean switchCl = deploymentCl != null && deploymentCl != originalTccl; - - try { - if (switchCl) { - // Set TCCL to the classloader that loaded this class, which should have access - // to the deployment classpath containing META-INF/services files - Thread.currentThread().setContextClassLoader(deploymentCl); - } - AgentCardValidator.validateTransportConfiguration(agentCard); - } finally { - if (switchCl) { - Thread.currentThread().setContextClassLoader(originalTccl); - } - } - } - - protected ClassLoader getDeploymentClassLoader() { - return this.getClass().getClassLoader(); - } - - public static void setStreamingSubscribedRunnable(Runnable runnable) { - streamingSubscribedRunnable = runnable; - } - - protected abstract RequestHandler getRequestHandler(); - - protected abstract AgentCard getAgentCard(); - - protected abstract AgentCard getExtendedAgentCard(); - - protected abstract CallContextFactory getCallContextFactory(); - - protected abstract Executor getExecutor(); - - /** - * Attempts to extract the X-A2A-Version header from the current gRPC context. - * This will only work if a server interceptor has been configured to capture - * the metadata and store it in the context. - * - * @return the version header value, or null if not available - */ - private @Nullable String getVersionFromContext() { - try { - return GrpcContextKeys.VERSION_HEADER_KEY.get(); - } catch (Exception e) { - // Context not available or key not set - return null; - } - } - - /** - * Attempts to extract the X-A2A-Extensions header from the current gRPC context. - * This will only work if a server interceptor has been configured to capture - * the metadata and store it in the context. - * - * @return the extensions header value, or null if not available - */ - private @Nullable String getExtensionsFromContext() { - try { - return GrpcContextKeys.EXTENSIONS_HEADER_KEY.get(); - } catch (Exception e) { - // Context not available or key not set - return null; - } - } - - /** - * Utility methods for accessing gRPC context information. - * These provide equivalent functionality to Python's grpc.aio.ServicerContext methods. - */ - - /** - * Generic helper method to safely access gRPC context values. - * - * @param key the context key to retrieve - * @return the context value, or null if not available - */ - private static @Nullable T getFromContext(Context.Key key) { - try { - return key.get(); - } catch (Exception e) { - // Context not available or key not set - return null; - } - } - - /** - * Gets the complete gRPC metadata from the current context. - * Equivalent to Python's context.invocation_metadata. - * - * @return the gRPC Metadata object, or null if not available - */ - protected static io.grpc.@Nullable Metadata getCurrentMetadata() { - return getFromContext(GrpcContextKeys.METADATA_KEY); - } - - /** - * Gets the current gRPC method name. - * Equivalent to Python's context.method(). - * - * @return the method name, or null if not available - */ - protected static @Nullable String getCurrentMethodName() { - return getFromContext(GrpcContextKeys.GRPC_METHOD_NAME_KEY); - } - - /** - * Gets the peer information for the current gRPC call. - * Equivalent to Python's context.peer(). - * - * @return the peer information, or null if not available - */ - protected static @Nullable String getCurrentPeerInfo() { - return getFromContext(GrpcContextKeys.PEER_INFO_KEY); - } -} diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java deleted file mode 100644 index 0cc667b2d..000000000 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/package-info.java +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ -@NullMarked -package io.a2a.transport.grpc.handler; - -import org.jspecify.annotations.NullMarked; - diff --git a/transport/grpc/src/main/resources/META-INF/beans.xml b/transport/grpc/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 9b2940fc2..000000000 --- a/transport/grpc/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java b/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java deleted file mode 100644 index fac5ce02c..000000000 --- a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java +++ /dev/null @@ -1,1284 +0,0 @@ -package io.a2a.transport.grpc.handler; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.google.protobuf.Empty; -import com.google.protobuf.Struct; - -import io.a2a.grpc.*; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.events.EventConsumer; -import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; -import io.a2a.server.requesthandlers.DefaultRequestHandler; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Artifact; -import io.a2a.spec.Event; -import io.a2a.spec.InternalError; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; -import io.grpc.Status; -import io.grpc.StatusRuntimeException; -import io.grpc.internal.testing.StreamRecorder; -import io.grpc.stub.StreamObserver; -import mutiny.zero.ZeroPublisher; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; -import org.mockito.MockedConstruction; -import org.mockito.Mockito; - -@Timeout(value = 1, unit = TimeUnit.MINUTES) -public class GrpcHandlerTest extends AbstractA2ARequestHandlerTest { - - private static final Message GRPC_MESSAGE = Message.newBuilder() - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .setContextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .setMessageId(AbstractA2ARequestHandlerTest.MESSAGE.messageId()) - .setRole(Role.ROLE_AGENT) - .addParts(Part.newBuilder() - .setText(((TextPart) AbstractA2ARequestHandlerTest.MESSAGE.parts().get(0)).text()) - .setMetadata(Struct.newBuilder().build()) - .build()) - .setMetadata(Struct.newBuilder().build()) - .build(); - - @Test - public void testOnGetTaskSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - GetTaskRequest request = GetTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.getTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - Task task = result.get(0); - assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), task.getId()); - assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), task.getContextId()); - assertEquals(TaskState.TASK_STATE_SUBMITTED, task.getStatus().getState()); - } - - @Test - public void testOnGetTaskNotFound() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - GetTaskRequest request = GetTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.getTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); - } - - @Test - public void testOnCancelTaskSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - - agentExecutorCancel = (context, agentEmitter) -> { - // We need to cancel the task or the EventConsumer never finds a 'final' event. - // Looking at the Python implementation, they typically use AgentExecutors that - // don't support cancellation. So my theory is the Agent updates the task to the CANCEL status - io.a2a.spec.Task task = context.getTask(); - agentEmitter.cancel(); - }; - - CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.cancelTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - Task task = result.get(0); - assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), task.getId()); - assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), task.getContextId()); - assertEquals(TaskState.TASK_STATE_CANCELED, task.getStatus().getState()); - } - - @Test - public void testOnCancelTaskNotSupported() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - - agentExecutorCancel = (context, agentEmitter) -> { - throw new UnsupportedOperationError(); - }; - - CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.cancelTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testOnCancelTaskNotFound() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - CancelTaskRequest request = CancelTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.cancelTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); - } - - @Test - public void testOnMessageNewMessageSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - StreamRecorder streamRecorder = sendMessageRequest(handler); - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - SendMessageResponse response = result.get(0); - assertEquals(GRPC_MESSAGE, response.getMessage()); - } - - @Test - public void testOnMessageNewMessageWithExistingTaskSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - StreamRecorder streamRecorder = sendMessageRequest(handler); - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - SendMessageResponse response = result.get(0); - assertEquals(GRPC_MESSAGE, response.getMessage()); - } - - @Test - public void testOnMessageError() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.fail(new UnsupportedOperationError()); - }; - StreamRecorder streamRecorder = sendMessageRequest(handler); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testSetPushNotificationConfigSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, - AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), "config456"); - - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - TaskPushNotificationConfig response = result.get(0); - assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); - PushNotificationConfig responseConfig = response.getPushNotificationConfig(); - assertEquals("config456", responseConfig.getId()); - assertEquals("config456", response.getId()); - assertEquals("http://example.com", responseConfig.getUrl()); - assertEquals(AuthenticationInfo.getDefaultInstance(), responseConfig.getAuthentication()); - Assertions.assertTrue(responseConfig.getToken().isEmpty()); - } - - @Test - public void testGetPushNotificationConfigSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - // first set the task push notification config - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, - AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), "config456"); - Assertions.assertNull(streamRecorder.getError()); - - // then get the task push notification config - streamRecorder = getTaskPushNotificationConfigRequest(handler, AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), "config456"); - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - TaskPushNotificationConfig response = result.get(0); - assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), response.getTaskId()); - assertEquals("config456", response.getId()); - PushNotificationConfig responseConfig = response.getPushNotificationConfig(); - assertEquals("config456", responseConfig.getId()); - assertEquals("http://example.com", responseConfig.getUrl()); - assertEquals(AuthenticationInfo.getDefaultInstance(), responseConfig.getAuthentication()); - Assertions.assertTrue(responseConfig.getToken().isEmpty()); - } - - @Test - public void testPushNotificationsNotSupportedError() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); - GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, - AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testOnGetPushNotificationNoPushNotifierConfig() throws Exception { - // Create request handler without a push notifier - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); - GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - StreamRecorder streamRecorder = getTaskPushNotificationConfigRequest(handler, - AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testOnSetPushNotificationNoPushNotifierConfig() throws Exception { - // Create request handler without a push notifier - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); - GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - StreamRecorder streamRecorder = createTaskPushNotificationConfigRequest(handler, - AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testOnMessageStreamNewMessageSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - Assertions.assertEquals(1, result.size()); - StreamResponse response = result.get(0); - Assertions.assertTrue(response.hasMessage()); - Message message = response.getMessage(); - Assertions.assertEquals(GRPC_MESSAGE, message); - } - - @Test - public void testOnMessageStreamNewMessageExistingTaskSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - io.a2a.spec.Task task = io.a2a.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) - .history(new ArrayList<>()) - .build(); - taskStore.save(task, false); - - List results = new ArrayList<>(); - List errors = new ArrayList<>(); - final CountDownLatch latch = new CountDownLatch(1); - httpClient.latch = latch; - StreamObserver streamObserver = new StreamObserver<>() { - @Override - public void onNext(StreamResponse streamResponse) { - results.add(streamResponse); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - errors.add(throwable); - } - - @Override - public void onCompleted() { - } - }; - sendStreamingMessageRequest(handler, streamObserver); - Assertions.assertTrue(latch.await(1, TimeUnit.SECONDS)); - Assertions.assertTrue(errors.isEmpty()); - Assertions.assertEquals(1, results.size()); - StreamResponse response = results.get(0); - Assertions.assertTrue(response.hasTask()); - Task taskResponse = response.getTask(); - - Task expected = Task.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .setContextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .addAllHistory(List.of(GRPC_MESSAGE)) - .setStatus(TaskStatus.newBuilder().setStateValue(TaskState.TASK_STATE_SUBMITTED_VALUE)) - .build(); - assertEquals(expected.getId(), taskResponse.getId()); - assertEquals(expected.getContextId(), taskResponse.getContextId()); - assertEquals(expected.getStatus().getState(), taskResponse.getStatus().getState()); - assertEquals(expected.getHistoryList(), taskResponse.getHistoryList()); - } - - @Test - public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - - io.a2a.spec.Task task = io.a2a.spec.Task.builder(AbstractA2ARequestHandlerTest.MINIMAL_TASK) - .history(new ArrayList<>()) - .build(); - taskStore.save(task, false); - - // This is used to send events from a mock - List events = List.of( - TaskArtifactUpdateEvent.builder() - .taskId(task.id()) - .contextId(task.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(task.id()) - .contextId(task.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_WORKING)) - .build()); - - StreamRecorder streamRecorder; - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll(); - })) { - streamRecorder = sendStreamingMessageRequest(handler); - } - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertEquals(2, result.size()); - StreamResponse first = result.get(0); - Assertions.assertTrue(first.hasArtifactUpdate()); - io.a2a.grpc.TaskArtifactUpdateEvent taskArtifactUpdateEvent = first.getArtifactUpdate(); - assertEquals(task.id(), taskArtifactUpdateEvent.getTaskId()); - assertEquals(task.contextId(), taskArtifactUpdateEvent.getContextId()); - assertEquals("11", taskArtifactUpdateEvent.getArtifact().getArtifactId()); - assertEquals("text", taskArtifactUpdateEvent.getArtifact().getParts(0).getText()); - StreamResponse second = result.get(1); - Assertions.assertTrue(second.hasStatusUpdate()); - io.a2a.grpc.TaskStatusUpdateEvent taskStatusUpdateEvent = second.getStatusUpdate(); - assertEquals(task.id(), taskStatusUpdateEvent.getTaskId()); - assertEquals(task.contextId(), taskStatusUpdateEvent.getContextId()); - assertEquals(TaskState.TASK_STATE_WORKING, taskStatusUpdateEvent.getStatus().getState()); - } - - @Test - public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Exception { - // Use synchronous executor for push notifications to ensure deterministic ordering - // Without this, async push notifications can execute out of order, causing test flakiness - mainEventBusProcessor.setPushNotificationExecutor(Runnable::run); - - try { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - List events = List.of( - AbstractA2ARequestHandlerTest.MINIMAL_TASK, - TaskArtifactUpdateEvent.builder() - .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_COMPLETED)) - .build()); - - agentExecutorExecute = (context, agentEmitter) -> { - // Hardcode the events to send here - for (Event event : events) { - agentEmitter.emitEvent(event); - } - }; - - StreamRecorder pushStreamRecorder = createTaskPushNotificationConfigRequest( - handler, AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - Assertions.assertNull(pushStreamRecorder.getError()); - - List results = new ArrayList<>(); - List errors = new ArrayList<>(); - final CountDownLatch latch = new CountDownLatch(6); - httpClient.latch = latch; - StreamObserver streamObserver = new StreamObserver<>() { - @Override - public void onNext(StreamResponse streamResponse) { - results.add(streamResponse); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - errors.add(throwable); - } - - @Override - public void onCompleted() { - } - }; - sendStreamingMessageRequest(handler, streamObserver); - Assertions.assertTrue(latch.await(5, TimeUnit.SECONDS)); - Assertions.assertTrue(errors.isEmpty()); - Assertions.assertEquals(3, results.size()); - Assertions.assertEquals(3, httpClient.events.size()); - - // Event 0: Task event - Assertions.assertTrue(httpClient.events.get(0) instanceof io.a2a.spec.Task, "First event should be Task"); - io.a2a.spec.Task task1 = (io.a2a.spec.Task) httpClient.events.get(0); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), task1.id()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), task1.contextId()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.status().state(), task1.status().state()); - Assertions.assertEquals(0, task1.artifacts() == null ? 0 : task1.artifacts().size()); - - // Event 1: TaskArtifactUpdateEvent - Assertions.assertTrue(httpClient.events.get(1) instanceof TaskArtifactUpdateEvent, "Second event should be TaskArtifactUpdateEvent"); - TaskArtifactUpdateEvent artifactUpdate = (TaskArtifactUpdateEvent) httpClient.events.get(1); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), artifactUpdate.taskId()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), artifactUpdate.contextId()); - Assertions.assertEquals(1, artifactUpdate.artifact().parts().size()); - Assertions.assertEquals("text", ((TextPart) artifactUpdate.artifact().parts().get(0)).text()); - - // Event 2: TaskStatusUpdateEvent - Assertions.assertTrue(httpClient.events.get(2) instanceof TaskStatusUpdateEvent, "Third event should be TaskStatusUpdateEvent"); - TaskStatusUpdateEvent statusUpdate = (TaskStatusUpdateEvent) httpClient.events.get(2); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), statusUpdate.taskId()); - Assertions.assertEquals(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId(), statusUpdate.contextId()); - Assertions.assertEquals(io.a2a.spec.TaskState.TASK_STATE_COMPLETED, statusUpdate.status().state()); - } finally { - mainEventBusProcessor.setPushNotificationExecutor(null); - } - } - - @Test - public void testOnSubscribeNoExistingTaskError() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.subscribeToTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); - } - - @Test - public void testOnSubscribeExistingTaskSuccess() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - queueManager.createOrTap(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - StreamRecorder streamRecorder = StreamRecorder.create(); - SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - handler.subscribeToTask(request, streamRecorder); - - // We need to send some events in order for those to end up in the queue - SendMessageRequest sendMessageRequest = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder messageRecorder = StreamRecorder.create(); - handler.sendStreamingMessage(sendMessageRequest, messageRecorder); - messageRecorder.awaitCompletion(5, TimeUnit.SECONDS); - Assertions.assertNull(messageRecorder.getError()); - - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - List result = streamRecorder.getValues(); - Assertions.assertNotNull(result); - // Per A2A Protocol Spec 3.1.6, subscribe sends current Task as first event, - // followed by the Message from the agent executor - Assertions.assertEquals(2, result.size()); - - // ENFORCE that first event is Task - Assertions.assertTrue(result.get(0).hasTask(), - "First event on subscribe MUST be Task (current state)"); - - // Second event should be Message from agent executor - StreamResponse response = result.get(1); - Assertions.assertTrue(response.hasMessage(), - "Expected Message after initial Task"); - assertEquals(GRPC_MESSAGE, response.getMessage()); - Assertions.assertNull(streamRecorder.getError()); - } - - @Test - public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - queueManager.createOrTap(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - - List events = List.of( - TaskArtifactUpdateEvent.builder() - .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .contextId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.contextId()) - .status(new io.a2a.spec.TaskStatus(io.a2a.spec.TaskState.TASK_STATE_WORKING)) - .build()); - - StreamRecorder streamRecorder = StreamRecorder.create(); - SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll(); - })) { - handler.subscribeToTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - } - List result = streamRecorder.getValues(); - Assertions.assertEquals(events.size(), result.size()); - StreamResponse first = result.get(0); - Assertions.assertTrue(first.hasArtifactUpdate()); - io.a2a.grpc.TaskArtifactUpdateEvent event = first.getArtifactUpdate(); - assertEquals("11", event.getArtifact().getArtifactId()); - assertEquals("text", (event.getArtifact().getParts(0)).getText()); - StreamResponse second = result.get(1); - Assertions.assertTrue(second.hasStatusUpdate()); - assertEquals(TaskState.TASK_STATE_WORKING, second.getStatusUpdate().getStatus().getState()); - } - - @Test - public void testStreamingNotSupportedError() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); - GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); - assertGrpcError(streamRecorder, Status.Code.INVALID_ARGUMENT); - } - - @Test - public void testStreamingNotSupportedErrorOnSubscribeToTask() throws Exception { - // This test does not exist in the Python implementation - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(false, true); - GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - SubscribeToTaskRequest request = SubscribeToTaskRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.subscribeToTask(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - assertGrpcError(streamRecorder, Status.Code.INVALID_ARGUMENT); - } - - @Test - public void testOnMessageStreamInternalError() throws Exception { - DefaultRequestHandler mocked = Mockito.mock(DefaultRequestHandler.class); - Mockito.doThrow(new InternalError("Internal Error")).when(mocked).onMessageSendStream(Mockito.any(MessageSendParams.class), Mockito.any(ServerCallContext.class)); - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, mocked, internalExecutor); - StreamRecorder streamRecorder = sendStreamingMessageRequest(handler); - assertGrpcError(streamRecorder, Status.Code.INTERNAL); - } - - @Test - public void testListPushNotificationConfig() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, - AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - Assertions.assertNull(pushRecorder.getError()); - - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); - Assertions.assertNull(streamRecorder.getError()); - List result = streamRecorder.getValues(); - Assertions.assertEquals(1, result.size()); - List configList = result.get(0).getConfigsList(); - Assertions.assertEquals(1, configList.size()); - Assertions.assertEquals(pushRecorder.getValues().get(0), configList.get(0)); - } - - @Test - public void testListPushNotificationConfigNotSupported() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); - GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testListPushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testListPushNotificationConfigTaskNotFound() { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - ListTaskPushNotificationConfigRequest request = ListTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.listTaskPushNotificationConfig(request, streamRecorder); - assertGrpcError(streamRecorder, Status.Code.NOT_FOUND); - } - - @Test - public void testDeletePushNotificationConfig() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - StreamRecorder pushRecorder = createTaskPushNotificationConfigRequest(handler, AbstractA2ARequestHandlerTest.MINIMAL_TASK.id(), - AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()); - Assertions.assertNull(pushRecorder.getError()); - - DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.deleteTaskPushNotificationConfig(request, streamRecorder); - Assertions.assertNull(streamRecorder.getError()); - Assertions.assertEquals(1, streamRecorder.getValues().size()); - assertEquals(Empty.getDefaultInstance(), streamRecorder.getValues().get(0)); - } - - @Test - public void testDeletePushNotificationConfigNotSupported() throws Exception { - AgentCard card = AbstractA2ARequestHandlerTest.createAgentCard(true, false); - GrpcHandler handler = new TestGrpcHandler(card, requestHandler, internalExecutor); - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.deleteTaskPushNotificationConfig(request, streamRecorder); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testDeletePushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - DeleteTaskPushNotificationConfigRequest request = DeleteTaskPushNotificationConfigRequest.newBuilder() - .setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .setTaskId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id()) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.deleteTaskPushNotificationConfig(request, streamRecorder); - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Disabled - public void testOnGetExtendedAgentCard() throws Exception { - // TODO - getting the authenticated extended agent card isn't supported for gRPC right now - } - - @Test - public void testStreamingDoesNotBlockMainThread() throws Exception { - GrpcHandler handler = new TestGrpcHandler(AbstractA2ARequestHandlerTest.CARD, requestHandler, internalExecutor); - - // Track if the main thread gets blocked during streaming - AtomicBoolean eventReceived = new AtomicBoolean(false); - CountDownLatch streamStarted = new CountDownLatch(1); - GrpcHandler.setStreamingSubscribedRunnable(streamStarted::countDown); - CountDownLatch eventProcessed = new CountDownLatch(1); - agentExecutorExecute = (context, agentEmitter) -> { - // Wait a bit to ensure the main thread continues - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - agentEmitter.sendMessage(context.getMessage()); - }; - - // Start streaming with a custom StreamObserver - List results = new ArrayList<>(); - List errors = new ArrayList<>(); - StreamObserver streamObserver = new StreamObserver<>() { - @Override - public void onNext(StreamResponse streamResponse) { - results.add(streamResponse); - eventReceived.set(true); - eventProcessed.countDown(); - } - - @Override - public void onError(Throwable throwable) { - errors.add(throwable); - eventProcessed.countDown(); - } - - @Override - public void onCompleted() { - eventProcessed.countDown(); - } - }; - - sendStreamingMessageRequest(handler, streamObserver); - - // The main thread should not be blocked - we should be able to continue immediately - Assertions.assertTrue(streamStarted.await(100, TimeUnit.MILLISECONDS), - "Streaming subscription should start quickly without blocking main thread"); - - // This proves the main thread is not blocked - we can do other work - // Simulate main thread doing other work - Thread.sleep(50); - - // Wait for the actual event processing to complete - Assertions.assertTrue(eventProcessed.await(2, TimeUnit.SECONDS), - "Event should be processed within reasonable time"); - - // Verify we received the event and no errors occurred - Assertions.assertTrue(eventReceived.get(), "Should have received streaming event"); - Assertions.assertTrue(errors.isEmpty(), "Should not have any errors"); - Assertions.assertEquals(1, results.size(), "Should have received exactly one event"); - } - - @Test - public void testExtensionSupportRequiredErrorOnSendMessage() throws Exception { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/test-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - GrpcHandler handler = new TestGrpcHandler(cardWithExtension, requestHandler, internalExecutor); - - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION); - } - - @Test - public void testExtensionSupportRequiredErrorOnSendStreamingMessage() throws Exception { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/streaming-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - GrpcHandler handler = new TestGrpcHandler(cardWithExtension, requestHandler, internalExecutor); - - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendStreamingMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - assertGrpcError(streamRecorder, Status.Code.FAILED_PRECONDITION); - } - - @Test - public void testRequiredExtensionProvidedSuccess() throws Exception { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/required-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - // Create a TestGrpcHandler that provides the required extension in the context - GrpcHandler handler = new TestGrpcHandler(cardWithExtension, requestHandler, internalExecutor) { - @Override - protected CallContextFactory getCallContextFactory() { - return new CallContextFactory() { - @Override - public ServerCallContext create(StreamObserver streamObserver) { - Set requestedExtensions = new HashSet<>(); - requestedExtensions.add("https://example.com/required-extension"); - return new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("grpc_response_observer", streamObserver), - requestedExtensions - ); - } - }; - } - }; - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - // Should succeed without error - Assertions.assertNull(streamRecorder.getError()); - Assertions.assertFalse(streamRecorder.getValues().isEmpty()); - } - - @Test - public void testVersionNotSupportedErrorOnSendMessage() throws Exception { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - // Create handler that provides incompatible version 2.0 in the context - GrpcHandler handler = new TestGrpcHandler(agentCard, requestHandler, internalExecutor) { - @Override - protected CallContextFactory getCallContextFactory() { - return new CallContextFactory() { - @Override - public ServerCallContext create(StreamObserver streamObserver) { - return new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("grpc_response_observer", streamObserver), - new HashSet<>(), - "2.0" // Incompatible version - ); - } - }; - } - }; - - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testVersionNotSupportedErrorOnSendStreamingMessage() throws Exception { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - // Create handler that provides incompatible version 2.0 in the context - GrpcHandler handler = new TestGrpcHandler(agentCard, requestHandler, internalExecutor) { - @Override - protected CallContextFactory getCallContextFactory() { - return new CallContextFactory() { - @Override - public ServerCallContext create(StreamObserver streamObserver) { - return new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("grpc_response_observer", streamObserver), - new HashSet<>(), - "2.0" // Incompatible version - ); - } - }; - } - }; - - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendStreamingMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED); - } - - @Test - public void testCompatibleVersionSuccess() throws Exception { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - // Create handler that provides compatible version 1.1 in the context - GrpcHandler handler = new TestGrpcHandler(agentCard, requestHandler, internalExecutor) { - @Override - protected CallContextFactory getCallContextFactory() { - return new CallContextFactory() { - @Override - public ServerCallContext create(StreamObserver streamObserver) { - return new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("grpc_response_observer", streamObserver), - new HashSet<>(), - "1.1" // Compatible version (same major version) - ); - } - }; - } - }; - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - // Should succeed without error - Assertions.assertNull(streamRecorder.getError()); - Assertions.assertFalse(streamRecorder.getValues().isEmpty()); - } - - @Test - public void testNoVersionDefaultsToCurrentVersionSuccess() throws Exception { - // Create AgentCard with protocol version 1.0 (current version) - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - // Create handler that provides null version (should default to 1.0) - GrpcHandler handler = new TestGrpcHandler(agentCard, requestHandler, internalExecutor) { - @Override - protected CallContextFactory getCallContextFactory() { - return new CallContextFactory() { - @Override - public ServerCallContext create(StreamObserver streamObserver) { - return new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("grpc_response_observer", streamObserver), - new HashSet<>(), - null // No version - should default to 1.0 - ); - } - }; - } - }; - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - - // Should succeed without error (defaults to 1.0) - Assertions.assertNull(streamRecorder.getError()); - Assertions.assertFalse(streamRecorder.getValues().isEmpty()); - } - - private StreamRecorder sendMessageRequest(GrpcHandler handler) throws Exception { - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - return streamRecorder; - } - - private StreamRecorder createTaskPushNotificationConfigRequest(GrpcHandler handler, String taskId, String id) throws Exception { - taskStore.save(AbstractA2ARequestHandlerTest.MINIMAL_TASK, false); - PushNotificationConfig config = PushNotificationConfig.newBuilder() - .setUrl("http://example.com") - .setId("config456") - .build(); - CreateTaskPushNotificationConfigRequest setRequest = CreateTaskPushNotificationConfigRequest.newBuilder() - .setConfig(config) - .setConfigId("config456") - .setTaskId(MINIMAL_TASK.id()) - .build(); - - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.createTaskPushNotificationConfig(setRequest, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - return streamRecorder; - } - - private StreamRecorder getTaskPushNotificationConfigRequest(GrpcHandler handler, String taskId, String id) throws Exception { - GetTaskPushNotificationConfigRequest request = GetTaskPushNotificationConfigRequest.newBuilder() - .setTaskId(taskId) - .setId(id) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.getTaskPushNotificationConfig(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - return streamRecorder; - } - - private StreamRecorder sendStreamingMessageRequest(GrpcHandler handler) throws Exception { - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - StreamRecorder streamRecorder = StreamRecorder.create(); - handler.sendStreamingMessage(request, streamRecorder); - streamRecorder.awaitCompletion(5, TimeUnit.SECONDS); - return streamRecorder; - } - - private void sendStreamingMessageRequest(GrpcHandler handler, StreamObserver streamObserver) throws Exception { - SendMessageRequest request = SendMessageRequest.newBuilder() - .setMessage(GRPC_MESSAGE) - .build(); - handler.sendStreamingMessage(request, streamObserver); - } - - private void assertGrpcError(StreamRecorder streamRecorder, Status.Code expectedStatusCode) { - Assertions.assertNotNull(streamRecorder.getError()); - Assertions.assertInstanceOf(StatusRuntimeException.class, streamRecorder.getError()); - Assertions.assertEquals(expectedStatusCode, ((StatusRuntimeException) streamRecorder.getError()).getStatus().getCode()); - Assertions.assertTrue(streamRecorder.getValues().isEmpty()); - } - - @Test - public void testListTasksNegativeTimestampReturnsInvalidArgument() { - TestGrpcHandler handler = new TestGrpcHandler(CARD, requestHandler, internalExecutor); - StreamRecorder responseObserver = StreamRecorder.create(); - - // Negative timestamp should trigger validation error - ListTasksRequest request = ListTasksRequest.newBuilder() - .setStatusTimestampAfter(com.google.protobuf.Timestamp.newBuilder().setSeconds(-1L).build()) - .setTenant("") - .build(); - - handler.listTasks(request, responseObserver); - - // Should return error with INVALID_ARGUMENT status - Assertions.assertTrue(responseObserver.getError() != null); - StatusRuntimeException error = (StatusRuntimeException) responseObserver.getError(); - assertEquals(Status.INVALID_ARGUMENT.getCode(), error.getStatus().getCode()); - } - - @Test - public void testListTasksEmptyResultIncludesAllFields() throws Exception { - TestGrpcHandler handler = new TestGrpcHandler(CARD, requestHandler, internalExecutor); - StreamRecorder responseObserver = StreamRecorder.create(); - - // Query for a context that doesn't exist - should return empty result - ListTasksRequest request = ListTasksRequest.newBuilder() - .setContextId("nonexistent-context-id") - .setTenant("") - .build(); - - handler.listTasks(request, responseObserver); - - // Should succeed with empty result - Assertions.assertNull(responseObserver.getError()); - List responses = responseObserver.getValues(); - assertEquals(1, responses.size()); - - ListTasksResponse response = responses.get(0); - // Verify all fields are present (even if empty/default) - Assertions.assertNotNull(response.getTasksList(), "tasks field should not be null"); - assertEquals(0, response.getTasksList().size(), "tasks should be empty list"); - assertEquals(0, response.getTotalSize(), "totalSize should be 0"); - assertEquals(0, response.getPageSize(), "pageSize should be 0"); - // nextPageToken will be empty string for empty results (protobuf default) - Assertions.assertNotNull(response.getNextPageToken()); - } - - private static class TestGrpcHandler extends GrpcHandler { - - private final AgentCard card; - private final RequestHandler handler; - private final java.util.concurrent.Executor executor; - - TestGrpcHandler(AgentCard card, RequestHandler handler, java.util.concurrent.Executor executor) { - this.card = card; - this.handler = handler; - this.executor = executor; - } - - @Override - protected RequestHandler getRequestHandler() { - return handler; - } - - @Override - protected AgentCard getAgentCard() { - return card; - } - - @Override - protected AgentCard getExtendedAgentCard() { - return card; - } - - @Override - protected CallContextFactory getCallContextFactory() { - return null; - } - - @Override - protected java.util.concurrent.Executor getExecutor() { - return executor; - } - } -} diff --git a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcTestTransportMetadata.java b/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcTestTransportMetadata.java deleted file mode 100644 index 5bdf4750d..000000000 --- a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcTestTransportMetadata.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.a2a.transport.grpc.handler; - -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; - -public class GrpcTestTransportMetadata implements TransportMetadata { - @Override - public String getTransportProtocol() { - return TransportProtocol.GRPC.asString(); - } - -} diff --git a/transport/grpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata b/transport/grpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index 8fce961b2..000000000 --- a/transport/grpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1,2 +0,0 @@ -# Add a test TransportMetadata so we pass AgentCard validation -io.a2a.transport.grpc.handler.GrpcTestTransportMetadata \ No newline at end of file diff --git a/transport/grpc/src/test/resources/a2a-requesthandler-test.properties b/transport/grpc/src/test/resources/a2a-requesthandler-test.properties deleted file mode 100644 index 102c971fb..000000000 --- a/transport/grpc/src/test/resources/a2a-requesthandler-test.properties +++ /dev/null @@ -1 +0,0 @@ -preferred-transport=GRPC \ No newline at end of file diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml deleted file mode 100644 index b8a285572..000000000 --- a/transport/jsonrpc/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-transport-jsonrpc - - jar - - Java SDK A2A Transport: JSONRPC - Java SDK for the Agent2Agent Protocol (A2A) - JSONRPC - - - - io.github.a2asdk - a2a-java-sdk-server-common - - - io.github.a2asdk - a2a-java-sdk-spec-grpc - - - io.github.a2asdk - a2a-java-sdk-spec - - - io.github.a2asdk - a2a-java-sdk-jsonrpc-common - ${project.version} - - - com.google.protobuf - protobuf-java-util - - - com.google.code.gson - gson - - - ${project.groupId} - a2a-java-sdk-server-common - test-jar - test - - - ch.qos.logback - logback-classic - test - - - org.junit.jupiter - junit-jupiter-api - test - - - org.mockito - mockito-core - test - - - - diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java deleted file mode 100644 index fbed22192..000000000 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/context/JSONRPCContextKeys.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.a2a.transport.jsonrpc.context; - -/** - * Shared JSON-RPC context keys for A2A protocol data. - * - * These keys provide access to JSON-RPC context information, - * enabling rich context access in service method implementations. - */ -public final class JSONRPCContextKeys { - - /** - * Context key for storing the headers. - */ - public static final String HEADERS_KEY = "headers"; - - /** - * Context key for storing the method name being called. - */ - public static final String METHOD_NAME_KEY = "method"; - - /** - * Context key for storing the tenant identifier extracted from the normalized path. - */ - public static final String TENANT_KEY = "tenant"; - - private JSONRPCContextKeys() { - // Utility class - } -} diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java deleted file mode 100644 index aa5ad4493..000000000 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java +++ /dev/null @@ -1,325 +0,0 @@ -package io.a2a.transport.jsonrpc.handler; - -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; -import io.a2a.server.AgentCardValidator; -import io.a2a.server.ExtendedAgentCard; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.ServerCallContext; -import io.a2a.server.extensions.A2AExtensions; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.util.async.Internal; -import io.a2a.server.version.A2AVersionValidator; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.EventKind; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; - -import mutiny.zero.ZeroPublisher; -import org.jspecify.annotations.Nullable; - -@ApplicationScoped -public class JSONRPCHandler { - - // Fields set by constructor injection cannot be final. We need a noargs constructor for - // Jakarta compatibility, and it seems that making fields set by constructor injection - // final, is not proxyable in all runtimes - private AgentCard agentCard; - private @Nullable Instance extendedAgentCard; - private RequestHandler requestHandler; - private Executor executor; - - /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. - */ - @SuppressWarnings("NullAway") - protected JSONRPCHandler() { - // For CDI proxy creation - this.agentCard = null; - this.extendedAgentCard = null; - this.requestHandler = null; - this.executor = null; - } - - @Inject - public JSONRPCHandler(@PublicAgentCard AgentCard agentCard, @Nullable @ExtendedAgentCard Instance extendedAgentCard, - RequestHandler requestHandler, @Internal Executor executor) { - this.agentCard = agentCard; - this.extendedAgentCard = extendedAgentCard; - this.requestHandler = requestHandler; - this.executor = executor; - - // Validate transport configuration - AgentCardValidator.validateTransportConfiguration(agentCard); - } - - public JSONRPCHandler(@PublicAgentCard AgentCard agentCard, RequestHandler requestHandler, Executor executor) { - this(agentCard, null, requestHandler, executor); - } - - public SendMessageResponse onMessageSend(SendMessageRequest request, ServerCallContext context) { - try { - A2AVersionValidator.validateProtocolVersion(agentCard, context); - A2AExtensions.validateRequiredExtensions(agentCard, context); - EventKind taskOrMessage = requestHandler.onMessageSend(request.getParams(), context); - return new SendMessageResponse(request.getId(), taskOrMessage); - } catch (A2AError e) { - return new SendMessageResponse(request.getId(), e); - } catch (Throwable t) { - return new SendMessageResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public Flow.Publisher onMessageSendStream( - SendStreamingMessageRequest request, ServerCallContext context) { - if (!agentCard.capabilities().streaming()) { - return ZeroPublisher.fromItems( - new SendStreamingMessageResponse( - request.getId(), - new InvalidRequestError("Streaming is not supported by the agent"))); - } - - try { - A2AVersionValidator.validateProtocolVersion(agentCard, context); - A2AExtensions.validateRequiredExtensions(agentCard, context); - Flow.Publisher publisher = - requestHandler.onMessageSendStream(request.getParams(), context); - // We can't use the convertingProcessor convenience method since that propagates any errors as an error handled - // via Subscriber.onError() rather than as part of the SendStreamingResponse payload - return convertToSendStreamingMessageResponse(request.getId(), publisher); - } catch (A2AError e) { - return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), e)); - } catch (Throwable throwable) { - return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), new InternalError(throwable.getMessage()))); - } - } - - public CancelTaskResponse onCancelTask(CancelTaskRequest request, ServerCallContext context) { - try { - Task task = requestHandler.onCancelTask(request.getParams(), context); - if (task != null) { - return new CancelTaskResponse(request.getId(), task); - } - return new CancelTaskResponse(request.getId(), new TaskNotFoundError()); - } catch (A2AError e) { - return new CancelTaskResponse(request.getId(), e); - } catch (Throwable t) { - return new CancelTaskResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public Flow.Publisher onSubscribeToTask( - SubscribeToTaskRequest request, ServerCallContext context) { - if (!agentCard.capabilities().streaming()) { - return ZeroPublisher.fromItems( - new SendStreamingMessageResponse( - request.getId(), - new InvalidRequestError("Streaming is not supported by the agent"))); - } - - try { - Flow.Publisher publisher = - requestHandler.onSubscribeToTask(request.getParams(), context); - // We can't use the convertingProcessor convenience method since that propagates any errors as an error handled - // via Subscriber.onError() rather than as part of the SendStreamingResponse payload - return convertToSendStreamingMessageResponse(request.getId(), publisher); - } catch (A2AError e) { - return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), e)); - } catch (Throwable throwable) { - return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), new InternalError(throwable.getMessage()))); - } - } - - public GetTaskPushNotificationConfigResponse getPushNotificationConfig( - GetTaskPushNotificationConfigRequest request, ServerCallContext context) { - if (!agentCard.capabilities().pushNotifications()) { - return new GetTaskPushNotificationConfigResponse(request.getId(), - new PushNotificationNotSupportedError()); - } - try { - TaskPushNotificationConfig config = - requestHandler.onGetTaskPushNotificationConfig(request.getParams(), context); - return new GetTaskPushNotificationConfigResponse(request.getId(), config); - } catch (A2AError e) { - return new GetTaskPushNotificationConfigResponse(request.getId().toString(), e); - } catch (Throwable t) { - return new GetTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public CreateTaskPushNotificationConfigResponse setPushNotificationConfig( - CreateTaskPushNotificationConfigRequest request, ServerCallContext context) { - if (!agentCard.capabilities().pushNotifications()) { - return new CreateTaskPushNotificationConfigResponse(request.getId(), - new PushNotificationNotSupportedError()); - } - try { - TaskPushNotificationConfig config = - requestHandler.onCreateTaskPushNotificationConfig(request.getParams(), context); - return new CreateTaskPushNotificationConfigResponse(request.getId().toString(), config); - } catch (A2AError e) { - return new CreateTaskPushNotificationConfigResponse(request.getId(), e); - } catch (Throwable t) { - return new CreateTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public GetTaskResponse onGetTask(GetTaskRequest request, ServerCallContext context) { - try { - Task task = requestHandler.onGetTask(request.getParams(), context); - return new GetTaskResponse(request.getId(), task); - } catch (A2AError e) { - return new GetTaskResponse(request.getId(), e); - } catch (Throwable t) { - return new GetTaskResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext context) { - try { - ListTasksResult result = requestHandler.onListTasks(request.getParams(), context); - return new ListTasksResponse(request.getId(), result); - } catch (A2AError e) { - return new ListTasksResponse(request.getId(), e); - } catch (Throwable t) { - return new ListTasksResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public ListTaskPushNotificationConfigResponse listPushNotificationConfig( - ListTaskPushNotificationConfigRequest request, ServerCallContext context) { - if ( !agentCard.capabilities().pushNotifications()) { - return new ListTaskPushNotificationConfigResponse(request.getId(), - new PushNotificationNotSupportedError()); - } - try { - ListTaskPushNotificationConfigResult result = - requestHandler.onListTaskPushNotificationConfig(request.getParams(), context); - return new ListTaskPushNotificationConfigResponse(request.getId(), result); - } catch (A2AError e) { - return new ListTaskPushNotificationConfigResponse(request.getId(), e); - } catch (Throwable t) { - return new ListTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public DeleteTaskPushNotificationConfigResponse deletePushNotificationConfig( - DeleteTaskPushNotificationConfigRequest request, ServerCallContext context) { - if ( !agentCard.capabilities().pushNotifications()) { - return new DeleteTaskPushNotificationConfigResponse(request.getId(), - new PushNotificationNotSupportedError()); - } - try { - requestHandler.onDeleteTaskPushNotificationConfig(request.getParams(), context); - return new DeleteTaskPushNotificationConfigResponse(request.getId()); - } catch (A2AError e) { - return new DeleteTaskPushNotificationConfigResponse(request.getId(), e); - } catch (Throwable t) { - return new DeleteTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - // TODO: Add authentication (https://github.com/a2aproject/a2a-java/issues/77) - public GetExtendedAgentCardResponse onGetExtendedCardRequest( - GetExtendedAgentCardRequest request, ServerCallContext context) { - if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { - return new GetExtendedAgentCardResponse(request.getId(), - new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null)); - } - try { - return new GetExtendedAgentCardResponse(request.getId(), extendedAgentCard.get()); - } catch (A2AError e) { - return new GetExtendedAgentCardResponse(request.getId(), e); - } catch (Throwable t) { - return new GetExtendedAgentCardResponse(request.getId(), new InternalError(t.getMessage())); - } - } - - public AgentCard getAgentCard() { - return agentCard; - } - - private Flow.Publisher convertToSendStreamingMessageResponse( - Object requestId, - Flow.Publisher publisher) { - // We can't use the normal convertingProcessor since that propagates any errors as an error handled - // via Subscriber.onError() rather than as part of the SendStreamingResponse payload - return ZeroPublisher.create(createTubeConfig(), tube -> { - CompletableFuture.runAsync(() -> { - publisher.subscribe(new Flow.Subscriber() { - @SuppressWarnings("NullAway") - Flow.Subscription subscription; - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(StreamingEventKind item) { - tube.send(new SendStreamingMessageResponse(requestId, item)); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - if (throwable instanceof A2AError jsonrpcError) { - tube.send(new SendStreamingMessageResponse(requestId, jsonrpcError)); - } else { - tube.send( - new SendStreamingMessageResponse( - requestId, new - InternalError(throwable.getMessage()))); - } - onComplete(); - } - - @Override - public void onComplete() { - tube.complete(); - } - }); - }, executor); - }); - } -} diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java deleted file mode 100644 index 20b7a9dde..000000000 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.transport.jsonrpc.handler; - -import org.jspecify.annotations.NullMarked; - diff --git a/transport/jsonrpc/src/main/resources/META-INF/beans.xml b/transport/jsonrpc/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 9b2940fc2..000000000 --- a/transport/jsonrpc/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java b/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java deleted file mode 100644 index 9087a1864..000000000 --- a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java +++ /dev/null @@ -1,1979 +0,0 @@ -package io.a2a.transport.jsonrpc.handler; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executors; -import java.util.concurrent.Flow; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; -import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.CreateTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardRequest; -import io.a2a.jsonrpc.common.wrappers.GetExtendedAgentCardResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; -import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; -import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; -import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; -import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; -import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.events.EventConsumer; -import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; -import io.a2a.server.requesthandlers.DefaultRequestHandler; -import io.a2a.server.tasks.ResultAggregator; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Artifact; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.Event; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.Message; -import io.a2a.spec.MessageSendConfiguration; -import io.a2a.spec.MessageSendParams; -import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.spec.TextPart; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.VersionNotSupportedError; -import mutiny.zero.ZeroPublisher; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; -import org.mockito.MockedConstruction; -import org.mockito.Mockito; - -@Timeout(value = 1, unit = TimeUnit.MINUTES) -public class JSONRPCHandlerTest extends AbstractA2ARequestHandlerTest { - - private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); - - private static MessageSendConfiguration defaultConfiguration() { - return MessageSendConfiguration.builder() - .acceptedOutputModes(List.of()) - .blocking(false) - .build(); - } - - @Test - public void testOnGetTaskSuccess() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - GetTaskRequest request = new GetTaskRequest("1", new TaskQueryParams(MINIMAL_TASK.id())); - GetTaskResponse response = handler.onGetTask(request, callContext); - assertEquals(request.getId(), response.getId()); - Assertions.assertSame(MINIMAL_TASK, response.getResult()); - assertNull(response.getError()); - } - - @Test - public void testOnGetTaskNotFound() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - GetTaskRequest request = new GetTaskRequest("1", new TaskQueryParams(MINIMAL_TASK.id())); - GetTaskResponse response = handler.onGetTask(request, callContext); - assertEquals(request.getId(), response.getId()); - assertInstanceOf(TaskNotFoundError.class, response.getError()); - assertNull(response.getResult()); - } - - @Test - public void testOnCancelTaskSuccess() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - agentExecutorCancel = (context, agentEmitter) -> { - // We need to cancel the task or the EventConsumer never finds a 'final' event. - // Looking at the Python implementation, they typically use AgentExecutors that - // don't support cancellation. So my theory is the Agent updates the task to the CANCEL status - Task task = context.getTask(); - agentEmitter.cancel(); - }; - - CancelTaskRequest request = new CancelTaskRequest("111", new TaskIdParams(MINIMAL_TASK.id())); - CancelTaskResponse response = handler.onCancelTask(request, callContext); - - assertNull(response.getError()); - assertEquals(request.getId(), response.getId()); - Task task = response.getResult(); - assertEquals(MINIMAL_TASK.id(), task.id()); - assertEquals(MINIMAL_TASK.contextId(), task.contextId()); - assertEquals(TaskState.TASK_STATE_CANCELED, task.status().state()); - } - - @Test - public void testOnCancelTaskNotSupported() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - agentExecutorCancel = (context, agentEmitter) -> { - throw new UnsupportedOperationError(); - }; - - CancelTaskRequest request = new CancelTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); - CancelTaskResponse response = handler.onCancelTask(request, callContext); - assertEquals(request.getId(), response.getId()); - assertNull(response.getResult()); - assertInstanceOf(UnsupportedOperationError.class, response.getError()); - } - - @Test - public void testOnCancelTaskNotFound() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - CancelTaskRequest request = new CancelTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); - CancelTaskResponse response = handler.onCancelTask(request, callContext); - assertEquals(request.getId(), response.getId()); - assertNull(response.getResult()); - assertInstanceOf(TaskNotFoundError.class, response.getError()); - } - - @Test - public void testOnMessageNewMessageSuccess() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); - assertNull(response.getError()); - Assertions.assertSame(message, response.getResult()); - } - - @Test - public void testOnMessageNewMessageWithExistingTaskSuccess() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); - assertNull(response.getError()); - Assertions.assertSame(message, response.getResult()); - } - - @Test - public void testOnMessageError() { - // See testMessageOnErrorMocks() for a test more similar to the Python implementation, using mocks for - // EventConsumer.consumeAll() - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.fail(new UnsupportedOperationError()); - }; - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest( - "1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); - assertInstanceOf(UnsupportedOperationError.class, response.getError()); - assertNull(response.getResult()); - } - - @Test - public void testOnMessageErrorMocks() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest( - "1", new MessageSendParams(message, null, null)); - SendMessageResponse response; - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromItems(wrapEvent(new UnsupportedOperationError()))).when(mock).consumeAll(); - })) { - response = handler.onMessageSend(request, callContext); - } - - assertInstanceOf(UnsupportedOperationError.class, response.getError()); - assertNull(response.getResult()); - } - - @Test - public void testOnMessageStreamNewMessageSuccess() throws InterruptedException { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - SendStreamingMessageRequest request = new SendStreamingMessageRequest( - "1", new MessageSendParams(message, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - List results = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(1); - - response.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item.getResult()); - subscription.request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - latch.await(); - - // The Python implementation has several events emitted since it uses mocks. Also, in the - // implementation, a Message is considered a 'final' Event in EventConsumer.consumeAll() - // so there would be no more Events. - // - // See testOnMessageStreamNewMessageSuccessMocks() for a test more similar to the Python implementation - assertEquals(1, results.size()); - Assertions.assertSame(message, results.get(0)); - } - - @Test - public void testOnMessageStreamNewMessageMultipleEventsSuccess() throws InterruptedException { - // Note: Do NOT set callback - DefaultRequestHandler has a permanent callback - // We'll verify persistence by checking TaskStore after streaming completes - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - - // Create multiple events to be sent during streaming - Task taskEvent = Task.builder(MINIMAL_TASK) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build(); - - TaskArtifactUpdateEvent artifactEvent = TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("artifact-1") - .parts(new TextPart("Generated artifact content")) - .build()) - .build(); - - TaskStatusUpdateEvent statusEvent = TaskStatusUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build(); - - // Configure the agent executor to enqueue multiple events - agentExecutorExecute = (context, agentEmitter) -> { - // Enqueue the task with WORKING state - agentEmitter.emitEvent(taskEvent); - // Enqueue an artifact update event - agentEmitter.emitEvent(artifactEvent); - // Enqueue a status update event to complete the task (this is the "final" event) - agentEmitter.emitEvent(statusEvent); - }; - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - SendStreamingMessageRequest request = new SendStreamingMessageRequest( - "1", new MessageSendParams(message, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - List results = new ArrayList<>(); - CountDownLatch latch = new CountDownLatch(3); // Expect 3 events - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item.getResult()); - subscription.request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - // Release latch to prevent timeout - while (latch.getCount() > 0) { - latch.countDown(); - } - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - // Wait for all events to be received (increased timeout for async processing) - assertTrue(latch.await(10, TimeUnit.SECONDS), - "Expected to receive 3 events within timeout"); - - // Assert no error occurred during streaming - Assertions.assertNull(error.get(), "No error should occur during streaming"); - - // Verify that all 3 events were received - assertEquals(3, results.size(), "Should have received exactly 3 events"); - - // Verify the first event is the task - Task receivedTask = assertInstanceOf(Task.class, results.get(0), "First event should be a Task"); - assertEquals(MINIMAL_TASK.id(), receivedTask.id()); - assertEquals(MINIMAL_TASK.contextId(), receivedTask.contextId()); - assertEquals(TaskState.TASK_STATE_WORKING, receivedTask.status().state()); - - // Verify the second event is the artifact update - TaskArtifactUpdateEvent receivedArtifact = assertInstanceOf(TaskArtifactUpdateEvent.class, results.get(1), - "Second event should be a TaskArtifactUpdateEvent"); - assertEquals(MINIMAL_TASK.id(), receivedArtifact.taskId()); - assertEquals("artifact-1", receivedArtifact.artifact().artifactId()); - - // Verify the third event is the status update - TaskStatusUpdateEvent receivedStatus = assertInstanceOf(TaskStatusUpdateEvent.class, results.get(2), - "Third event should be a TaskStatusUpdateEvent"); - assertEquals(MINIMAL_TASK.id(), receivedStatus.taskId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, receivedStatus.status().state()); - - // Verify events were persisted to TaskStore (poll for final state) - for (int i = 0; i < 50; i++) { - Task storedTask = taskStore.get(MINIMAL_TASK.id()); - if (storedTask != null && storedTask.status() != null - && TaskState.TASK_STATE_COMPLETED.equals(storedTask.status().state())) { - return; // Success - task finalized in TaskStore - } - Thread.sleep(100); - } - fail("Task should have been finalized in TaskStore within timeout"); - } - - @Test - public void testOnMessageStreamNewMessageSuccessMocks() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - - // This is used to send events from a mock - List events = List.of( - MINIMAL_TASK, - TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("art1") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - SendStreamingMessageRequest request = new SendStreamingMessageRequest( - "1", new MessageSendParams(message, null, null)); - Flow.Publisher response; - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll(); - })) { - response = handler.onMessageSendStream(request, callContext); - } - - CompletableFuture future = new CompletableFuture<>(); - List results = new ArrayList<>(); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add((Event) item.getResult()); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - future.completeExceptionally(throwable); - } - - @Override - public void onComplete() { - future.complete(null); - } - }); - - future.join(); - Assertions.assertEquals(events, results); - } - - @Test - public void testOnMessageStreamNewMessageExistingTaskSuccess() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - Task task = Task.builder(MINIMAL_TASK) - .history(new ArrayList<>()) - .build(); - taskStore.save(task, false); - - Message message = Message.builder(MESSAGE) - .taskId(task.id()) - .contextId(task.contextId()) - .build(); - - SendStreamingMessageRequest request = new SendStreamingMessageRequest( - "1", new MessageSendParams(message, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - // This Publisher never completes so we subscribe in a new thread. - // I _think_ that is as expected, and testOnMessageStreamNewMessageSendPushNotificationSuccess seems - // to confirm this - final List results = new ArrayList<>(); - final AtomicReference subscriptionRef = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(1); - - Executors.newSingleThreadExecutor().execute(() -> { - response.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscriptionRef.set(subscription); - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item.getResult()); - subscriptionRef.get().request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscriptionRef.get().cancel(); - } - - @Override - public void onComplete() { - subscriptionRef.get().cancel(); - } - }); - }); - - assertTrue(latch.await(1, TimeUnit.SECONDS)); - subscriptionRef.get().cancel(); - // The Python implementation has several events emitted since it uses mocks. - // - // See testOnMessageStreamNewMessageExistingTaskSuccessMocks() for a test more similar to the Python implementation - Task expected = Task.builder(task) - .history(message) - .build(); - assertEquals(1, results.size()); - StreamingEventKind receivedType = results.get(0); - assertInstanceOf(Task.class, receivedType); - Task received = (Task) receivedType; - assertEquals(expected.id(), received.id()); - assertEquals(expected.contextId(), received.contextId()); - assertEquals(expected.status(), received.status()); - assertEquals(expected.history(), received.history()); - } - - @Test - public void testOnMessageStreamNewMessageExistingTaskSuccessMocks() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - - Task task = Task.builder(MINIMAL_TASK) - .history(new ArrayList<>()) - .build(); - taskStore.save(task, false); - - // This is used to send events from a mock - List events = List.of( - TaskArtifactUpdateEvent.builder() - .taskId(task.id()) - .contextId(task.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(task.id()) - .contextId(task.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build()); - - Message message = Message.builder(MESSAGE) - .taskId(task.id()) - .contextId(task.contextId()) - .build(); - - SendStreamingMessageRequest request = new SendStreamingMessageRequest( - "1", new MessageSendParams(message, null, null)); - Flow.Publisher response; - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll(); - })) { - response = handler.onMessageSendStream(request, callContext); - } - - CompletableFuture future = new CompletableFuture<>(); - List results = new ArrayList<>(); - - // Unlike testOnMessageStreamNewMessageExistingTaskSuccess() the ZeroPublisher.fromIterable() - // used to mock the events completes once it has sent all the items. So no special thread - // handling is needed. - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add((Event) item.getResult()); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - future.completeExceptionally(throwable); - } - - @Override - public void onComplete() { - future.complete(null); - } - }); - - future.join(); - - Assertions.assertEquals(events, results); - } - - @Test - public void testSetPushNotificationConfigSuccess() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder().url("http://example.com") - .id("c295ea44-7543-4f78-b524-7a38915ad6e4").build(), - "tenant"); - CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); - CreateTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); - TaskPushNotificationConfig taskPushConfigResult - = new TaskPushNotificationConfig( MINIMAL_TASK.id(), - PushNotificationConfig.builder().url("http://example.com") - .id("c295ea44-7543-4f78-b524-7a38915ad6e4").build(), - "tenant"); - - Assertions.assertEquals(taskPushConfigResult, response.getResult()); - } - - @Test - public void testGetPushNotificationConfigSuccess() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); - - CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); - handler.setPushNotificationConfig(request, callContext); - - GetTaskPushNotificationConfigRequest getRequest - = new GetTaskPushNotificationConfigRequest("111", new GetTaskPushNotificationConfigParams( - MINIMAL_TASK.id(), - "c295ea44-7543-4f78-b524-7a38915ad6e4")); - GetTaskPushNotificationConfigResponse getResponse = handler.getPushNotificationConfig(getRequest, callContext); - - TaskPushNotificationConfig expectedConfig = new TaskPushNotificationConfig(MINIMAL_TASK.id(), - PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), ""); - - assertEquals(expectedConfig, getResponse.getResult()); - } - - @Test - public void testOnMessageStreamNewMessageSendPushNotificationSuccess() throws Exception { - // Note: Do NOT set callback - DefaultRequestHandler has a permanent callback - - // Use synchronous executor for push notifications to ensure deterministic ordering - // Without this, async push notifications can execute out of order, causing test flakiness - mainEventBusProcessor.setPushNotificationExecutor(Runnable::run); - - try { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - List events = List.of( - MINIMAL_TASK, - TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_COMPLETED)) - .build()); - - - agentExecutorExecute = (context, agentEmitter) -> { - // Hardcode the events to send here - for (Event event : events) { - agentEmitter.emitEvent(event); - } - }; - - TaskPushNotificationConfig config = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder().id("c295ea44-7543-4f78-b524-7a38915ad6e4").url("http://example.com").build(), "tenant"); - - CreateTaskPushNotificationConfigRequest stpnRequest = new CreateTaskPushNotificationConfigRequest("1", config); - CreateTaskPushNotificationConfigResponse stpnResponse = handler.setPushNotificationConfig(stpnRequest, callContext); - assertNull(stpnResponse.getError()); - - Message msg = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .build(); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(msg, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - final List results = Collections.synchronizedList(new ArrayList<>()); - final AtomicReference subscriptionRef = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(6); - httpClient.latch = latch; - - Executors.newSingleThreadExecutor().execute(() -> { - response.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscriptionRef.set(subscription); - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - System.out.println("-> " + item.getResult()); - results.add(item.getResult()); - System.out.println(results); - subscriptionRef.get().request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - subscriptionRef.get().cancel(); - } - - @Override - public void onComplete() { - subscriptionRef.get().cancel(); - } - }); - }); - - assertTrue(latch.await(5, TimeUnit.SECONDS)); - - subscriptionRef.get().cancel(); - assertEquals(3, results.size()); - // Push notifications now send the actual StreamingEventKind events, not Task snapshots - assertEquals(3, httpClient.events.size()); - - // Event 0: Task event - assertTrue(httpClient.events.get(0) instanceof Task, "First event should be Task"); - Task task1 = (Task) httpClient.events.get(0); - assertEquals(MINIMAL_TASK.id(), task1.id()); - assertEquals(MINIMAL_TASK.contextId(), task1.contextId()); - assertEquals(MINIMAL_TASK.status().state(), task1.status().state()); - assertEquals(0, task1.artifacts() == null ? 0 : task1.artifacts().size()); - - // Event 1: TaskArtifactUpdateEvent - assertTrue(httpClient.events.get(1) instanceof TaskArtifactUpdateEvent, "Second event should be TaskArtifactUpdateEvent"); - TaskArtifactUpdateEvent artifactUpdate = (TaskArtifactUpdateEvent) httpClient.events.get(1); - assertEquals(MINIMAL_TASK.id(), artifactUpdate.taskId()); - assertEquals(MINIMAL_TASK.contextId(), artifactUpdate.contextId()); - assertEquals(1, artifactUpdate.artifact().parts().size()); - assertEquals("text", ((TextPart) artifactUpdate.artifact().parts().get(0)).text()); - - // Event 2: TaskStatusUpdateEvent - assertTrue(httpClient.events.get(2) instanceof TaskStatusUpdateEvent, "Third event should be TaskStatusUpdateEvent"); - TaskStatusUpdateEvent statusUpdate = (TaskStatusUpdateEvent) httpClient.events.get(2); - assertEquals(MINIMAL_TASK.id(), statusUpdate.taskId()); - assertEquals(MINIMAL_TASK.contextId(), statusUpdate.contextId()); - assertEquals(TaskState.TASK_STATE_COMPLETED, statusUpdate.status().state()); - } finally { - mainEventBusProcessor.setPushNotificationExecutor(null); - } - } - - @Test - public void testOnSubscribeExistingTaskSuccess() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - queueManager.createOrTap(MINIMAL_TASK.id()); - - agentExecutorExecute = (context, agentEmitter) -> { - // The only thing hitting the agent is the onMessageSend() and we should use the message - agentEmitter.sendMessage(context.getMessage()); - //agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); - Flow.Publisher response = handler.onSubscribeToTask(request, callContext); - - // We need to send some events in order for those to end up in the queue - Message message = Message.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .role(Message.Role.ROLE_AGENT) - .parts(new TextPart("text")) - .build(); - SendMessageResponse smr - = handler.onMessageSend( - new SendMessageRequest("1", new MessageSendParams(message, null, null)), - callContext); - assertNull(smr.getError()); - - CompletableFuture future = new CompletableFuture<>(); - List results = new ArrayList<>(); - AtomicBoolean receivedInitialTask = new AtomicBoolean(false); - - response.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - StreamingEventKind event = item.getResult(); - results.add(event); - - // Per A2A Protocol Spec 3.1.6: ENFORCE that first event is Task - if (!receivedInitialTask.get()) { - assertTrue(event instanceof Task, - "First event on subscribe MUST be Task (current state), but was: " + event.getClass().getSimpleName()); - receivedInitialTask.set(true); - } else { - // Subsequent events should be the expected type (Message in this case) - assertTrue(event instanceof Message, - "Expected Message after initial Task, but was: " + event.getClass().getSimpleName()); - } - - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - future.completeExceptionally(throwable); - } - - @Override - public void onComplete() { - subscription.cancel(); - future.complete(null); - } - }); - - future.join(); - - // Verify we received exactly 2 events and the initial Task was received - assertEquals(2, results.size()); - assertTrue(receivedInitialTask.get(), "Should have received initial Task event"); - } - - @Test - public void testOnSubscribeExistingTaskSuccessMocks() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - queueManager.createOrTap(MINIMAL_TASK.id()); - - List events = List.of( - TaskArtifactUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .artifact(Artifact.builder() - .artifactId("11") - .parts(new TextPart("text")) - .build()) - .build(), - TaskStatusUpdateEvent.builder() - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .status(new TaskStatus(TaskState.TASK_STATE_WORKING)) - .build()); - - SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); - Flow.Publisher response; - try (MockedConstruction mocked = Mockito.mockConstruction( - EventConsumer.class, - (mock, context) -> { - Mockito.doReturn(ZeroPublisher.fromIterable(events.stream().map(AbstractA2ARequestHandlerTest::wrapEvent).toList())).when(mock).consumeAll(); - })) { - response = handler.onSubscribeToTask(request, callContext); - } - - CompletableFuture future = new CompletableFuture<>(); - List results = new ArrayList<>(); - - // Unlike testOnSubscribeExistingTaskSuccess() the ZeroPublisher.fromIterable() - // used to mock the events completes once it has sent all the items. So no special thread - // handling is needed. - response.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item.getResult()); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - future.completeExceptionally(throwable); - } - - @Override - public void onComplete() { - subscription.cancel(); - future.complete(null); - } - }); - - future.join(); - - // The Python implementation has several events emitted since it uses mocks. - // - // See testOnMessageStreamNewMessageExistingTaskSuccessMocks() for a test more similar to the Python implementation - assertEquals(events, results); - } - - @Test - public void testOnSubscribeNoExistingTaskError() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - - SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); - Flow.Publisher response = handler.onSubscribeToTask(request, callContext); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber<>() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - assertEquals(1, results.size()); - assertNull(results.get(0).getResult()); - assertInstanceOf(TaskNotFoundError.class, results.get(0).getError()); - } - - @Test - public void testStreamingNotSupportedError() { - AgentCard card = createAgentCard(false, true); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - - SendStreamingMessageRequest request = SendStreamingMessageRequest.builder() - .id("1") - .params(MessageSendParams.builder() - .message(MESSAGE) - .configuration(defaultConfiguration()) - .build()) - .build(); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - assertEquals(1, results.size()); - if (results.get(0).getError() != null && results.get(0).getError() instanceof InvalidRequestError ire) { - assertEquals("Streaming is not supported by the agent", ire.getMessage()); - } else { - fail("Expected a response containing an error"); - } - } - - @Test - public void testStreamingNotSupportedErrorOnSubscribeToTask() { - // This test does not exist in the Python implementation - AgentCard card = createAgentCard(false, true); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - - SubscribeToTaskRequest request = new SubscribeToTaskRequest("1", new TaskIdParams(MINIMAL_TASK.id())); - Flow.Publisher response = handler.onSubscribeToTask(request, callContext); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - assertEquals(1, results.size()); - if (results.get(0).getError() != null && results.get(0).getError() instanceof InvalidRequestError ire) { - assertEquals("Streaming is not supported by the agent", ire.getMessage()); - } else { - fail("Expected a response containing an error"); - } - } - - @Test - public void testPushNotificationsNotSupportedError() { - AgentCard card = createAgentCard(true, false); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - TaskPushNotificationConfig config - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4") - .url("http://example.com") - .build(), "tenant"); - - CreateTaskPushNotificationConfigRequest request = CreateTaskPushNotificationConfigRequest.builder() - .params(config) - .build(); - CreateTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); - assertInstanceOf(PushNotificationNotSupportedError.class, response.getError()); - } - - @Test - public void testOnGetPushNotificationNoPushNotifierConfig() { - // Create request handler without a push notifier - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = createAgentCard(false, true); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - - taskStore.save(MINIMAL_TASK, false); - - GetTaskPushNotificationConfigRequest request - = new GetTaskPushNotificationConfigRequest("id", new GetTaskPushNotificationConfigParams( - MINIMAL_TASK.id(),"c295ea44-7543-4f78-b524-7a38915ad6e4")); - GetTaskPushNotificationConfigResponse response = handler.getPushNotificationConfig(request, callContext); - - Assertions.assertNotNull(response.getError()); - assertInstanceOf(UnsupportedOperationError.class, response.getError()); - assertEquals("This operation is not supported", response.getError().getMessage()); - } - - @Test - public void testOnSetPushNotificationNoPushNotifierConfig() { - // Create request handler without a push notifier - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = createAgentCard(false, true); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - - taskStore.save(MINIMAL_TASK, false); - - TaskPushNotificationConfig config - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), - PushNotificationConfig.builder() - .id("c295ea44-7543-4f78-b524-7a38915ad6e4") - .url("http://example.com") - .build(), "tenant"); - - CreateTaskPushNotificationConfigRequest request = CreateTaskPushNotificationConfigRequest.builder() - .params(config) - .build(); - CreateTaskPushNotificationConfigResponse response = handler.setPushNotificationConfig(request, callContext); - - assertInstanceOf(UnsupportedOperationError.class, response.getError()); - assertEquals("This operation is not supported", response.getError().getMessage()); - } - - @Test - public void testOnMessageSendInternalError() { - DefaultRequestHandler mocked = Mockito.mock(DefaultRequestHandler.class); - Mockito.doThrow(new InternalError("Internal Error")).when(mocked) - .onMessageSend(Mockito.any(MessageSendParams.class), Mockito.any(ServerCallContext.class)); - - JSONRPCHandler handler = new JSONRPCHandler(CARD, mocked, internalExecutor); - - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(MESSAGE, defaultConfiguration(), null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); - - assertInstanceOf(InternalError.class, response.getError()); - } - - @Test - public void testOnMessageStreamInternalError() { - DefaultRequestHandler mocked = Mockito.mock(DefaultRequestHandler.class); - Mockito.doThrow(new InternalError("Internal Error")).when(mocked) - .onMessageSendStream(Mockito.any(MessageSendParams.class), Mockito.any(ServerCallContext.class)); - - JSONRPCHandler handler = new JSONRPCHandler(CARD, mocked, internalExecutor); - - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, defaultConfiguration(), null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - assertEquals(1, results.size()); - assertInstanceOf(InternalError.class, results.get(0).getError()); - } - - @Test - @Disabled - public void testDefaultRequestHandlerWithCustomComponents() { - // Not much happening in the Python test beyond checking that the DefaultRequestHandler - // constructor sets the fields as expected - } - - @Test - public void testOnMessageSendErrorHandling() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - AgentCard card = createAgentCard(false, true); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - - taskStore.save(MINIMAL_TASK, false); - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response; - - try (MockedConstruction mocked = Mockito.mockConstruction( - ResultAggregator.class, - (mock, context) -> { - Mockito.doThrow( - new UnsupportedOperationError()) - .when(mock).consumeAndBreakOnInterrupt( - Mockito.any(EventConsumer.class), - Mockito.anyBoolean()); - })) { - response = handler.onMessageSend(request, callContext); - } - - assertInstanceOf(UnsupportedOperationError.class, response.getError()); - - } - - @Test - public void testOnMessageSendTaskIdMismatch() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - agentExecutorExecute = ((context, agentEmitter) -> { - agentEmitter.emitEvent(MINIMAL_TASK); - }); - SendMessageRequest request = new SendMessageRequest("1", - new MessageSendParams(MESSAGE, defaultConfiguration(), null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); - assertInstanceOf(InternalError.class, response.getError()); - - } - - @Test - public void testOnMessageStreamTaskIdMismatch() throws InterruptedException { - // Note: Do NOT set callback - DefaultRequestHandler has a permanent callback - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - agentExecutorExecute = ((context, agentEmitter) -> { - agentEmitter.emitEvent(MINIMAL_TASK); - }); - - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(MESSAGE, defaultConfiguration(), null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - CompletableFuture future = new CompletableFuture<>(); - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - future.completeExceptionally(throwable); - } - - @Override - public void onComplete() { - subscription.cancel(); - future.complete(null); - } - }); - - future.join(); - - Assertions.assertNull(error.get()); - Assertions.assertEquals(1, results.size()); - Assertions.assertInstanceOf(InternalError.class, results.get(0).getError()); - } - - @Test - public void testListPushNotificationConfig() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") - .id(MINIMAL_TASK.id()) - .build(), "tenant"); - CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); - handler.setPushNotificationConfig(request, callContext); - TaskPushNotificationConfig result = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") - .id(MINIMAL_TASK.id()) - .build(), ""); - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse = handler.listPushNotificationConfig(listRequest, callContext); - - assertEquals("111", listResponse.getId()); - assertEquals(1, listResponse.getResult().size()); - assertEquals(result, listResponse.getResult().configs().get(0)); - } - - @Test - public void testListPushNotificationConfigNotSupported() { - AgentCard card = createAgentCard(true, false); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") - .id(MINIMAL_TASK.id()) - .build(), "tenant"); - CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); - handler.setPushNotificationConfig(request, callContext); - - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse - = handler.listPushNotificationConfig(listRequest, callContext); - - assertEquals("111", listResponse.getId()); - assertNull(listResponse.getResult()); - assertInstanceOf(PushNotificationNotSupportedError.class, listResponse.getError()); - } - - @Test - public void testListPushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse - = handler.listPushNotificationConfig(listRequest, callContext); - - assertEquals("111", listResponse.getId()); - assertNull(listResponse.getResult()); - assertInstanceOf(UnsupportedOperationError.class, listResponse.getError()); - } - - @Test - public void testListPushNotificationConfigTaskNotFound() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - ListTaskPushNotificationConfigRequest listRequest - = new ListTaskPushNotificationConfigRequest("111", new ListTaskPushNotificationConfigParams(MINIMAL_TASK.id())); - ListTaskPushNotificationConfigResponse listResponse - = handler.listPushNotificationConfig(listRequest, callContext); - - assertEquals("111", listResponse.getId()); - assertNull(listResponse.getResult()); - assertInstanceOf(TaskNotFoundError.class, listResponse.getError()); - } - - @Test - public void testDeletePushNotificationConfig() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") - .id(MINIMAL_TASK.id()) - .build(), "tenant"); - CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); - handler.setPushNotificationConfig(request, callContext); - - DeleteTaskPushNotificationConfigRequest deleteRequest - = new DeleteTaskPushNotificationConfigRequest("111", new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), MINIMAL_TASK.id())); - DeleteTaskPushNotificationConfigResponse deleteResponse - = handler.deletePushNotificationConfig(deleteRequest, callContext); - - assertEquals("111", deleteResponse.getId()); - assertNull(deleteResponse.getError()); - assertNull(deleteResponse.getResult()); - } - - @Test - public void testDeletePushNotificationConfigNotSupported() { - AgentCard card = createAgentCard(true, false); - JSONRPCHandler handler = new JSONRPCHandler(card, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") - .id(MINIMAL_TASK.id()) - .build(), "tenant"); - CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); - handler.setPushNotificationConfig(request, callContext); - - DeleteTaskPushNotificationConfigRequest deleteRequest - = new DeleteTaskPushNotificationConfigRequest("111", new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), MINIMAL_TASK.id())); - DeleteTaskPushNotificationConfigResponse deleteResponse - = handler.deletePushNotificationConfig(deleteRequest, callContext); - - assertEquals("111", deleteResponse.getId()); - assertNull(deleteResponse.getResult()); - assertInstanceOf(PushNotificationNotSupportedError.class, deleteResponse.getError()); - } - - @Test - public void testDeletePushNotificationConfigNoPushConfigStore() { - DefaultRequestHandler requestHandler = - DefaultRequestHandler.create(executor, taskStore, queueManager, null, mainEventBusProcessor, internalExecutor, internalExecutor); - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.emitEvent(context.getTask() != null ? context.getTask() : context.getMessage()); - }; - - TaskPushNotificationConfig taskPushConfig - = new TaskPushNotificationConfig( - MINIMAL_TASK.id(), PushNotificationConfig.builder() - .url("http://example.com") - .id(MINIMAL_TASK.id()) - .build(), "tenant"); - CreateTaskPushNotificationConfigRequest request = new CreateTaskPushNotificationConfigRequest("1", taskPushConfig); - handler.setPushNotificationConfig(request, callContext); - - DeleteTaskPushNotificationConfigRequest deleteRequest - = new DeleteTaskPushNotificationConfigRequest("111", new DeleteTaskPushNotificationConfigParams(MINIMAL_TASK.id(), MINIMAL_TASK.id())); - DeleteTaskPushNotificationConfigResponse deleteResponse - = handler.deletePushNotificationConfig(deleteRequest, callContext); - - assertEquals("111", deleteResponse.getId()); - assertNull(deleteResponse.getResult()); - assertInstanceOf(UnsupportedOperationError.class, deleteResponse.getError()); - } - - @Test - public void testOnGetExtendedAgentCard() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - GetExtendedAgentCardRequest request = new GetExtendedAgentCardRequest("1"); - GetExtendedAgentCardResponse response = handler.onGetExtendedCardRequest(request, callContext); - assertEquals(request.getId(), response.getId()); - assertInstanceOf(ExtendedAgentCardNotConfiguredError.class, response.getError()); - assertNull(response.getResult()); - } - - @Test - public void testStreamingDoesNotBlockMainThread() throws Exception { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - - // Track if the main thread gets blocked during streaming - AtomicBoolean mainThreadBlocked = new AtomicBoolean(true); - AtomicBoolean eventReceived = new AtomicBoolean(false); - CountDownLatch streamStarted = new CountDownLatch(1); - CountDownLatch eventProcessed = new CountDownLatch(1); - - agentExecutorExecute = (context, agentEmitter) -> { - // Wait a bit to ensure the main thread continues - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - agentEmitter.sendMessage(context.getMessage()); - }; - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(message, null, null)); - - // Start streaming - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - streamStarted.countDown(); - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - eventReceived.set(true); - eventProcessed.countDown(); - subscription.cancel(); - } - - @Override - public void onError(Throwable throwable) { - subscription.cancel(); - eventProcessed.countDown(); - } - - @Override - public void onComplete() { - subscription.cancel(); - eventProcessed.countDown(); - } - }); - - // The main thread should not be blocked - we should be able to continue immediately - assertTrue(streamStarted.await(100, TimeUnit.MILLISECONDS), - "Streaming subscription should start quickly without blocking main thread"); - - // This proves the main thread is not blocked - we can do other work - // Simulate main thread doing other work - Thread.sleep(50); - - mainThreadBlocked.set(false); // If we get here, main thread was not blocked - - // Wait for the actual event processing to complete - assertTrue(eventProcessed.await(2, TimeUnit.SECONDS), - "Event should be processed within reasonable time"); - - // Verify we received the event and main thread was not blocked - assertTrue(eventReceived.get(), "Should have received streaming event"); - Assertions.assertFalse(mainThreadBlocked.get(), "Main thread should not have been blocked"); - } - - @Test - public void testExtensionSupportRequiredErrorOnMessageSend() { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("JSONRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/test-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); - - // Use callContext which has empty requestedExtensions set - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); - - assertInstanceOf(ExtensionSupportRequiredError.class, response.getError()); - assertTrue(response.getError().getMessage().contains("https://example.com/test-extension")); - assertNull(response.getResult()); - } - - @Test - public void testExtensionSupportRequiredErrorOnMessageSendStream() { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("JSONRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/streaming-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(message, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, callContext); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - subscription.cancel(); - } - - @Override - public void onComplete() { - subscription.cancel(); - } - }); - - assertEquals(1, results.size()); - assertInstanceOf(ExtensionSupportRequiredError.class, results.get(0).getError()); - assertTrue(results.get(0).getError().getMessage().contains("https://example.com/streaming-extension")); - assertNull(results.get(0).getResult()); - } - - @Test - public void testRequiredExtensionProvidedSuccess() { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("JSONRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/required-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - JSONRPCHandler handler = new JSONRPCHandler(cardWithExtension, requestHandler, internalExecutor); - - // Create context WITH the required extension - Set requestedExtensions = new HashSet<>(); - requestedExtensions.add("https://example.com/required-extension"); - ServerCallContext contextWithExtension = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - requestedExtensions - ); - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, contextWithExtension); - - // Should succeed without ExtensionSupportRequiredError - assertNull(response.getError()); - Assertions.assertSame(message, response.getResult()); - } - - @Test - public void testVersionNotSupportedErrorOnMessageSend() { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("JSONRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); - - // Create context with incompatible version 2.0 - ServerCallContext contextWithVersion = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - new HashSet<>(), - "2.0" // Incompatible version - ); - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, contextWithVersion); - - assertInstanceOf(VersionNotSupportedError.class, response.getError()); - assertTrue(response.getError().getMessage().contains("2.0")); - assertNull(response.getResult()); - } - - @Test - public void testVersionNotSupportedErrorOnMessageSendStream() throws Exception { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("JSONRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); - - // Create context with incompatible version 2.0 - ServerCallContext contextWithVersion = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - new HashSet<>(), - "2.0" // Incompatible version - ); - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendStreamingMessageRequest request = new SendStreamingMessageRequest("1", new MessageSendParams(message, null, null)); - Flow.Publisher response = handler.onMessageSendStream(request, contextWithVersion); - - List results = new ArrayList<>(); - AtomicReference error = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - - response.subscribe(new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(SendStreamingMessageResponse item) { - results.add(item); - subscription.request(1); - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - error.set(throwable); - latch.countDown(); - } - - @Override - public void onComplete() { - latch.countDown(); - } - }); - - // Wait for async processing - assertTrue(latch.await(2, TimeUnit.SECONDS), "Expected to receive error event within timeout"); - - assertEquals(1, results.size()); - SendStreamingMessageResponse result = results.get(0); - assertInstanceOf(VersionNotSupportedError.class, result.getError()); - assertTrue(result.getError().getMessage().contains("2.0")); - assertNull(result.getResult()); - } - - @Test - public void testCompatibleVersionSuccess() { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("JSONRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); - - // Create context with compatible version 1.1 - ServerCallContext contextWithVersion = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - new HashSet<>(), - "1.1" // Compatible version (same major version) - ); - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, contextWithVersion); - - // Should succeed without error - assertNull(response.getError()); - Assertions.assertSame(message, response.getResult()); - } - - @Test - public void testNoVersionDefaultsToCurrentVersionSuccess() { - // Create AgentCard with protocol version 1.0 (current version) - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("JSONRPC", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - JSONRPCHandler handler = new JSONRPCHandler(agentCard, requestHandler, internalExecutor); - - // Use default callContext (no version - should default to 1.0) - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - Message message = Message.builder(MESSAGE) - .taskId(MINIMAL_TASK.id()) - .contextId(MINIMAL_TASK.contextId()) - .build(); - SendMessageRequest request = new SendMessageRequest("1", new MessageSendParams(message, null, null)); - SendMessageResponse response = handler.onMessageSend(request, callContext); - - // Should succeed without error (defaults to 1.0) - assertNull(response.getError()); - Assertions.assertSame(message, response.getResult()); - } - - @Test - public void testListTasksEmptyResultIncludesAllFields() { - JSONRPCHandler handler = new JSONRPCHandler(CARD, requestHandler, internalExecutor); - - // Query for a context that doesn't exist - should return empty result - ListTasksParams params = ListTasksParams.builder() - .contextId("nonexistent-context-id") - .tenant("") - .build(); - ListTasksRequest request = new ListTasksRequest("1", params); - ListTasksResponse response = handler.onListTasks(request, callContext); - - // Should return success with all fields present (not null) - assertNull(response.getError()); - ListTasksResult result = response.getResult(); - Assertions.assertNotNull(result); - Assertions.assertNotNull(result.tasks(), "tasks field should not be null"); - assertEquals(0, result.tasks().size(), "tasks should be empty list"); - assertEquals(0, result.totalSize(), "totalSize should be 0"); - assertEquals(0, result.pageSize(), "pageSize should be 0"); - // nextPageToken can be null for empty results - } -} diff --git a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java b/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java deleted file mode 100644 index c2087cffc..000000000 --- a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCTestTransportMetadata.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.a2a.transport.jsonrpc.handler; - -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; - -public class JSONRPCTestTransportMetadata implements TransportMetadata { - @Override - public String getTransportProtocol() { - return TransportProtocol.JSONRPC.asString(); - } - -} diff --git a/transport/jsonrpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata b/transport/jsonrpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index e4ec9c45f..000000000 --- a/transport/jsonrpc/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1,2 +0,0 @@ -# Add a test TransportMetadata so we pass AgentCard validation -io.a2a.transport.jsonrpc.handler.JSONRPCTestTransportMetadata \ No newline at end of file diff --git a/transport/jsonrpc/src/test/resources/a2a-requesthandler-test.properties b/transport/jsonrpc/src/test/resources/a2a-requesthandler-test.properties deleted file mode 100644 index c069ffd5c..000000000 --- a/transport/jsonrpc/src/test/resources/a2a-requesthandler-test.properties +++ /dev/null @@ -1 +0,0 @@ -preferred-transport=JSONRPC \ No newline at end of file diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml deleted file mode 100644 index 4bc82fb52..000000000 --- a/transport/rest/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - 4.0.0 - - - io.github.a2asdk - a2a-java-sdk-parent - 1.0.0.Alpha4-SNAPSHOT - ../../pom.xml - - a2a-java-sdk-transport-rest - - jar - - Java SDK A2A Transport: JSON+HTTP/REST - Java SDK for the Agent2Agent Protocol (A2A) - JSON+HTTP/REST Transport - - - - io.github.a2asdk - a2a-java-sdk-server-common - - - io.github.a2asdk - a2a-java-sdk-spec-grpc - - - io.github.a2asdk - a2a-java-sdk-spec - - - io.github.a2asdk - a2a-java-sdk-jsonrpc-common - ${project.version} - - - ${project.groupId} - a2a-java-sdk-server-common - test-jar - test - - - ch.qos.logback - logback-classic - test - - - org.junit.jupiter - junit-jupiter-api - test - - - org.mockito - mockito-core - test - - - com.google.protobuf - protobuf-java-util - - - org.slf4j - slf4j-jdk14 - test - - - - - \ No newline at end of file diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java b/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java deleted file mode 100644 index f822607ef..000000000 --- a/transport/rest/src/main/java/io/a2a/transport/rest/context/RestContextKeys.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.a2a.transport.rest.context; - -/** - * Shared REST context keys for A2A protocol data. - * - * These keys provide access to REST context information, - * enabling rich context access in service method implementations. - */ -public final class RestContextKeys { - - /** - * Context key for storing the headers. - */ - public static final String HEADERS_KEY = "headers"; - - /** - * Context key for storing the method name being called. - */ - public static final String METHOD_NAME_KEY = "method"; - /** - * Context key for storing the tenant identifier extracted from the request path. - */ - public static final String TENANT_KEY = "tenant"; - - private RestContextKeys() { - // Utility class - } -} diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java b/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java deleted file mode 100644 index 7312824c2..000000000 --- a/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java +++ /dev/null @@ -1,547 +0,0 @@ -package io.a2a.transport.rest.handler; - -import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; - -import java.time.Instant; -import java.time.format.DateTimeParseException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.Flow; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.util.JsonFormat; -import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.jsonrpc.common.json.JsonUtil; -import io.a2a.jsonrpc.common.wrappers.ListTasksResult; -import io.a2a.server.AgentCardValidator; -import io.a2a.server.ExtendedAgentCard; -import io.a2a.server.PublicAgentCard; -import io.a2a.server.ServerCallContext; -import io.a2a.server.extensions.A2AExtensions; -import io.a2a.server.requesthandlers.RequestHandler; -import io.a2a.server.version.A2AVersionValidator; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.A2AError; -import io.a2a.spec.AgentCard; -import io.a2a.spec.ExtendedAgentCardNotConfiguredError; -import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.EventKind; -import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidAgentResponseError; -import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONParseError; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksParams; -import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.Task; -import io.a2a.spec.TaskIdParams; -import io.a2a.spec.TaskNotCancelableError; -import io.a2a.spec.TaskNotFoundError; -import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.TaskState; -import io.a2a.spec.UnsupportedOperationError; -import io.a2a.spec.ExtensionSupportRequiredError; -import io.a2a.spec.VersionNotSupportedError; -import mutiny.zero.ZeroPublisher; -import org.jspecify.annotations.Nullable; - -@ApplicationScoped -public class RestHandler { - - private static final Logger log = Logger.getLogger(RestHandler.class.getName()); - private static final String TASK_STATE_PREFIX = "TASK_STATE_"; - - // Fields set by constructor injection cannot be final. We need a noargs constructor for - // Jakarta compatibility, and it seems that making fields set by constructor injection - // final, is not proxyable in all runtimes - private AgentCard agentCard; - private @Nullable Instance extendedAgentCard; - private RequestHandler requestHandler; - private Executor executor; - - /** - * No-args constructor for CDI proxy creation. - * CDI requires a non-private constructor to create proxies for @ApplicationScoped beans. - * All fields are initialized by the @Inject constructor during actual bean creation. - */ - @SuppressWarnings("NullAway") - protected RestHandler() { - // For CDI - this.executor = null; - } - - @Inject - public RestHandler(@PublicAgentCard AgentCard agentCard, @ExtendedAgentCard Instance extendedAgentCard, - RequestHandler requestHandler, @Internal Executor executor) { - this.agentCard = agentCard; - this.extendedAgentCard = extendedAgentCard; - this.requestHandler = requestHandler; - this.executor = executor; - - // Validate transport configuration - AgentCardValidator.validateTransportConfiguration(agentCard); - } - - public RestHandler(AgentCard agentCard, RequestHandler requestHandler, Executor executor) { - this.agentCard = agentCard; - this.requestHandler = requestHandler; - this.executor = executor; - } - - public HTTPRestResponse sendMessage(ServerCallContext context, String tenant, String body) { - - try { - A2AVersionValidator.validateProtocolVersion(agentCard, context); - A2AExtensions.validateRequiredExtensions(agentCard, context); - io.a2a.grpc.SendMessageRequest.Builder request = io.a2a.grpc.SendMessageRequest.newBuilder(); - parseRequestBody(body, request); - request.setTenant(tenant); - EventKind result = requestHandler.onMessageSend(ProtoUtils.FromProto.messageSendParams(request), context); - return createSuccessResponse(200, io.a2a.grpc.SendMessageResponse.newBuilder(ProtoUtils.ToProto.taskOrMessage(result))); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - public HTTPRestResponse sendStreamingMessage(ServerCallContext context, String tenant, String body) { - try { - if (!agentCard.capabilities().streaming()) { - return createErrorResponse(new InvalidRequestError("Streaming is not supported by the agent")); - } - A2AVersionValidator.validateProtocolVersion(agentCard, context); - A2AExtensions.validateRequiredExtensions(agentCard, context); - io.a2a.grpc.SendMessageRequest.Builder request = io.a2a.grpc.SendMessageRequest.newBuilder(); - parseRequestBody(body, request); - request.setTenant(tenant); - Flow.Publisher publisher = requestHandler.onMessageSendStream(ProtoUtils.FromProto.messageSendParams(request), context); - return createStreamingResponse(publisher); - } catch (A2AError e) { - return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); - } catch (Throwable throwable) { - return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(new InternalError(throwable.getMessage())).toJson())); - } - } - - public HTTPRestResponse cancelTask(ServerCallContext context, String tenant, String taskId) { - try { - if (taskId == null || taskId.isEmpty()) { - throw new InvalidParamsError(); - } - TaskIdParams params = new TaskIdParams(taskId, tenant); - Task task = requestHandler.onCancelTask(params, context); - if (task != null) { - return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); - } - throw new UnsupportedOperationError(); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - public HTTPRestResponse createTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String body, String taskId) { - try { - if (!agentCard.capabilities().pushNotifications()) { - throw new PushNotificationNotSupportedError(); - } - io.a2a.grpc.CreateTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.CreateTaskPushNotificationConfigRequest.newBuilder(); - parseRequestBody(body, builder); - builder.setTenant(tenant); - TaskPushNotificationConfig result = requestHandler.onCreateTaskPushNotificationConfig(ProtoUtils.FromProto.CreateTaskPushNotificationConfig(builder), context); - return createSuccessResponse(201, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(result))); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - public HTTPRestResponse subscribeToTask(ServerCallContext context, String tenant, String taskId) { - try { - if (!agentCard.capabilities().streaming()) { - return createErrorResponse(new InvalidRequestError("Streaming is not supported by the agent")); - } - TaskIdParams params = new TaskIdParams(taskId, tenant); - Flow.Publisher publisher = requestHandler.onSubscribeToTask(params, context); - return createStreamingResponse(publisher); - } catch (A2AError e) { - return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); - } catch (Throwable throwable) { - return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(new InternalError(throwable.getMessage())).toJson())); - } - } - - public HTTPRestResponse getTask(ServerCallContext context, String tenant, String taskId, @Nullable Integer historyLength) { - try { - TaskQueryParams params = new TaskQueryParams(taskId, historyLength, tenant); - Task task = requestHandler.onGetTask(params, context); - if (task != null) { - return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); - } - throw new TaskNotFoundError(); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - public HTTPRestResponse listTasks(ServerCallContext context, String tenant, - @Nullable String contextId, @Nullable String status, - @Nullable Integer pageSize, @Nullable String pageToken, - @Nullable Integer historyLength, @Nullable String statusTimestampAfter, - @Nullable Boolean includeArtifacts) { - try { - // Build params - ListTasksParams.Builder paramsBuilder = ListTasksParams.builder(); - if (contextId != null) { - paramsBuilder.contextId(contextId); - } - if (status != null) { - TaskState taskState; - - try { - taskState = TaskState.valueOf(status); - } catch (IllegalArgumentException e) { - String validStates = Arrays.stream(TaskState.values()) - .map(TaskState::name) - .collect(Collectors.joining(", ")); - Map errorData = new HashMap<>(); - errorData.put("parameter", "status"); - errorData.put("reason", "Must be one of: " + validStates); - throw new InvalidParamsError(null, "Invalid params", errorData); - } - - paramsBuilder.status(taskState); - } - if (pageSize != null) { - paramsBuilder.pageSize(pageSize); - } - if (pageToken != null) { - paramsBuilder.pageToken(pageToken); - } - if (historyLength != null) { - paramsBuilder.historyLength(historyLength); - } - paramsBuilder.tenant(tenant); - if (statusTimestampAfter != null) { - try { - paramsBuilder.statusTimestampAfter(Instant.parse(statusTimestampAfter)); - } catch (DateTimeParseException e) { - Map errorData = new HashMap<>(); - errorData.put("parameter", "statusTimestampAfter"); - errorData.put("reason", "Must be an ISO-8601 timestamp"); - throw new InvalidParamsError(null, "Invalid params", errorData); - } - } - if (includeArtifacts != null) { - paramsBuilder.includeArtifacts(includeArtifacts); - } - ListTasksParams params = paramsBuilder.build(); - - ListTasksResult result = requestHandler.onListTasks(params, context); - return createSuccessResponse(200, io.a2a.grpc.ListTasksResponse.newBuilder(ProtoUtils.ToProto.listTasksResult(result))); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - public HTTPRestResponse getTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String taskId, String configId) { - try { - if (!agentCard.capabilities().pushNotifications()) { - throw new PushNotificationNotSupportedError(); - } - GetTaskPushNotificationConfigParams params = new GetTaskPushNotificationConfigParams(taskId, configId, tenant); - TaskPushNotificationConfig config = requestHandler.onGetTaskPushNotificationConfig(params, context); - return createSuccessResponse(200, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(config))); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - public HTTPRestResponse listTaskPushNotificationConfigurations(ServerCallContext context, String tenant, String taskId, int pageSize, String pageToken) { - try { - if (!agentCard.capabilities().pushNotifications()) { - throw new PushNotificationNotSupportedError(); - } - ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, pageSize, pageToken, tenant); - ListTaskPushNotificationConfigResult result = requestHandler.onListTaskPushNotificationConfig(params, context); - return createSuccessResponse(200, io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder(ProtoUtils.ToProto.listTaskPushNotificationConfigResponse(result))); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - public HTTPRestResponse deleteTaskPushNotificationConfiguration(ServerCallContext context, String tenant, String taskId, String configId) { - try { - if (!agentCard.capabilities().pushNotifications()) { - throw new PushNotificationNotSupportedError(); - } - DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams(taskId, configId, tenant); - requestHandler.onDeleteTaskPushNotificationConfig(params, context); - return new HTTPRestResponse(204, "application/json", ""); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable throwable) { - return createErrorResponse(new InternalError(throwable.getMessage())); - } - } - - private void parseRequestBody(String body, com.google.protobuf.Message.Builder builder) throws A2AError { - try { - if (body == null || body.trim().isEmpty()) { - throw new InvalidRequestError("Request body is required"); - } - validate(body); - JsonFormat.parser().merge(body, builder); - } catch (InvalidProtocolBufferException e) { - log.log(Level.SEVERE, "Error parsing JSON request body: {0}", body); - log.log(Level.SEVERE, "Parse error details", e); - throw new InvalidParamsError("Failed to parse request body: " + e.getMessage()); - } - } - - private void validate(String json) { - try { - JsonParser.parseString(json); - } catch (JsonSyntaxException e) { - throw new JSONParseError(JSON_PARSE_ERROR_CODE, "Failed to parse json", e.getMessage()); - } - } - - private HTTPRestResponse createSuccessResponse(int statusCode, com.google.protobuf.Message.Builder builder) { - try { - // Include default value fields to ensure empty arrays, zeros, etc. are present in JSON - String jsonBody = JsonFormat.printer().includingDefaultValueFields().print(builder); - return new HTTPRestResponse(statusCode, "application/json", jsonBody); - } catch (InvalidProtocolBufferException e) { - return createErrorResponse(new InternalError("Failed to serialize response: " + e.getMessage())); - } - } - - public HTTPRestResponse createErrorResponse(A2AError error) { - int statusCode = mapErrorToHttpStatus(error); - return createErrorResponse(statusCode, error); - } - - private HTTPRestResponse createErrorResponse(int statusCode, A2AError error) { - String jsonBody = new HTTPRestErrorResponse(error).toJson(); - return new HTTPRestResponse(statusCode, "application/json", jsonBody); - } - - private HTTPRestStreamingResponse createStreamingResponse(Flow.Publisher publisher) { - return new HTTPRestStreamingResponse(convertToSendStreamingMessageResponse(publisher)); - } - - @SuppressWarnings("FutureReturnValueIgnored") - private Flow.Publisher convertToSendStreamingMessageResponse( - Flow.Publisher publisher) { - // We can't use the normal convertingProcessor since that propagates any errors as an error handled - // via Subscriber.onError() rather than as part of the SendStreamingResponse payload - log.log(Level.FINE, "REST: convertToSendStreamingMessageResponse called, creating ZeroPublisher"); - return ZeroPublisher.create(createTubeConfig(), tube -> { - log.log(Level.FINE, "REST: ZeroPublisher tube created, starting CompletableFuture.runAsync"); - CompletableFuture.runAsync(() -> { - log.log(Level.FINE, "REST: Inside CompletableFuture, subscribing to EventKind publisher"); - publisher.subscribe(new Flow.Subscriber() { - Flow.@Nullable Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - log.log(Level.FINE, "REST: onSubscribe called, storing subscription and requesting first event"); - this.subscription = subscription; - subscription.request(1); - } - - @Override - public void onNext(StreamingEventKind item) { - log.log(Level.FINE, "REST: onNext called with event: {0}", item.getClass().getSimpleName()); - try { - String payload = JsonFormat.printer().omittingInsignificantWhitespace().print(ProtoUtils.ToProto.taskOrMessageStream(item)); - log.log(Level.FINE, "REST: Converted to JSON, sending via tube: {0}", payload.substring(0, Math.min(100, payload.length()))); - tube.send(payload); - log.log(Level.FINE, "REST: tube.send() completed, requesting next event from EventConsumer"); - // Request next event from EventConsumer (Chain 1: EventConsumer → RestHandler) - // This is safe because ZeroPublisher buffers items - // Chain 2 (ZeroPublisher → MultiSseSupport) controls actual delivery via request(1) in onWriteDone() - if (subscription != null) { - subscription.request(1); - } else { - log.log(Level.WARNING, "REST: subscription is null in onNext!"); - } - } catch (InvalidProtocolBufferException ex) { - log.log(Level.SEVERE, "REST: JSON conversion failed", ex); - onError(ex); - } - } - - @Override - public void onError(Throwable throwable) { - log.log(Level.SEVERE, "REST: onError called", throwable); - if (throwable instanceof A2AError jsonrpcError) { - tube.send(new HTTPRestErrorResponse(jsonrpcError).toJson()); - } else { - tube.send(new HTTPRestErrorResponse(new InternalError(throwable.getMessage())).toJson()); - } - onComplete(); - } - - @Override - public void onComplete() { - log.log(Level.FINE, "REST: onComplete called, calling tube.complete()"); - tube.complete(); - } - }); - }, executor); - }); - } - - private int mapErrorToHttpStatus(A2AError error) { - if (error instanceof InvalidRequestError || error instanceof JSONParseError) { - return 400; - } - if (error instanceof InvalidParamsError) { - return 422; - } - if (error instanceof MethodNotFoundError || error instanceof TaskNotFoundError) { - return 404; - } - if (error instanceof TaskNotCancelableError) { - return 409; - } - if (error instanceof PushNotificationNotSupportedError - || error instanceof UnsupportedOperationError - || error instanceof VersionNotSupportedError) { - return 501; - } - if (error instanceof ContentTypeNotSupportedError) { - return 415; - } - if (error instanceof InvalidAgentResponseError) { - return 502; - } - if (error instanceof ExtendedAgentCardNotConfiguredError - || error instanceof ExtensionSupportRequiredError) { - return 400; - } - if (error instanceof InternalError) { - return 500; - } - return 500; - } - - public HTTPRestResponse getExtendedAgentCard(ServerCallContext context, String tenant) { - try { - if (!agentCard.capabilities().extendedAgentCard() || extendedAgentCard == null || !extendedAgentCard.isResolvable()) { - throw new ExtendedAgentCardNotConfiguredError(null, "Extended Card not configured", null); - } - return new HTTPRestResponse(200, "application/json", JsonUtil.toJson(extendedAgentCard.get())); - } catch (A2AError e) { - return createErrorResponse(e); - } catch (Throwable t) { - return createErrorResponse(500, new InternalError(t.getMessage())); - } - } - - public HTTPRestResponse getAgentCard() { - try { - return new HTTPRestResponse(200, "application/json", JsonUtil.toJson(agentCard)); - } catch (Throwable t) { - return createErrorResponse(500, new InternalError(t.getMessage())); - } - } - - public static class HTTPRestResponse { - - private final int statusCode; - private final String contentType; - private final String body; - - public HTTPRestResponse(int statusCode, String contentType, String body) { - this.statusCode = statusCode; - this.contentType = contentType; - this.body = body; - } - - public int getStatusCode() { - return statusCode; - } - - public String getContentType() { - return contentType; - } - - public String getBody() { - return body; - } - - @Override - public String toString() { - return "HTTPRestResponse{" + "statusCode=" + statusCode + ", contentType=" + contentType + ", body=" + body + '}'; - } - } - - public static class HTTPRestStreamingResponse extends HTTPRestResponse { - - private final Flow.Publisher publisher; - - public HTTPRestStreamingResponse(Flow.Publisher publisher) { - super(200, "text/event-stream", ""); - this.publisher = publisher; - } - - public Flow.Publisher getPublisher() { - return publisher; - } - } - - private static class HTTPRestErrorResponse { - - private final String error; - private final @Nullable - String message; - - private HTTPRestErrorResponse(A2AError jsonRpcError) { - this.error = jsonRpcError.getClass().getName(); - this.message = jsonRpcError.getMessage(); - } - - private String toJson() { - return "{\"error\": \"" + error + "\", \"message\": \"" + message + "\"}"; - } - - @Override - public String toString() { - return "HTTPRestErrorResponse{" + "error=" + error + ", message=" + message + '}'; - } - } -} diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java b/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java deleted file mode 100644 index 8d4e4063c..000000000 --- a/transport/rest/src/main/java/io/a2a/transport/rest/handler/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -@NullMarked -package io.a2a.transport.rest.handler; - -import org.jspecify.annotations.NullMarked; - diff --git a/transport/rest/src/main/resources/META-INF/beans.xml b/transport/rest/src/main/resources/META-INF/beans.xml deleted file mode 100644 index 0d9b1c17d..000000000 --- a/transport/rest/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java b/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java deleted file mode 100644 index cc0e8c303..000000000 --- a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java +++ /dev/null @@ -1,944 +0,0 @@ -package io.a2a.transport.rest.handler; - - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Flow; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import com.google.protobuf.InvalidProtocolBufferException; -import io.a2a.server.ServerCallContext; -import io.a2a.server.auth.UnauthenticatedUser; -import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentExtension; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.Task; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; - -@Timeout(value = 1, unit = TimeUnit.MINUTES) -public class RestHandlerTest extends AbstractA2ARequestHandlerTest { - - private final ServerCallContext callContext = new ServerCallContext(UnauthenticatedUser.INSTANCE, Map.of("foo", "bar"), new HashSet<>()); - - @Test - public void testGetTaskSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", MINIMAL_TASK.id(), 0); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); - - response = handler.getTask(callContext, "", MINIMAL_TASK.id(), 2); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); - } - - @Test - public void testGetTaskNotFound() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - RestHandler.HTTPRestResponse response = handler.getTask(callContext, "", "nonexistent", 0); - - Assertions.assertEquals(404, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); - } - - @Test - public void testListTasksStatusWireString() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "TASK_STATE_SUBMITTED", null, null, - null, null, null); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); - } - - @Test - public void testListTasksInvalidStatus() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "not-a-status", null, null, - null, null, null); - - Assertions.assertEquals(422, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); - } - - @Test - public void testSendMessage() throws InvalidProtocolBufferException { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - String requestBody = """ - { - "message": - { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": { - } - }, - "configuration": - { - "blocking": true - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); - Assertions.assertEquals(200, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertNotNull(response.getBody()); - } - - @Test - public void testSendMessageInvalidBody() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - String invalidBody = "invalid json"; - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", invalidBody); - - Assertions.assertEquals(400, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("JSONParseError"),response.getBody()); - } - - @Test - public void testSendMessageWrongValueBody() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - String requestBody = """ - { - "message": - { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "user", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": { - } - } - }"""; - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); - - Assertions.assertEquals(422, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); - } - - @Test - public void testSendMessageEmptyBody() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); - - Assertions.assertEquals(400, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("InvalidRequestError")); - } - - @Test - public void testCancelTaskSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - agentExecutorCancel = (context, agentEmitter) -> { - // We need to cancel the task or the EventConsumer never finds a 'final' event. - // Looking at the Python implementation, they typically use AgentExecutors that - // don't support cancellation. So my theory is the Agent updates the task to the CANCEL status - Task task = context.getTask(); - agentEmitter.cancel(); - }; - - RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", MINIMAL_TASK.id()); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); - } - - @Test - public void testCancelTaskNotFound() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - RestHandler.HTTPRestResponse response = handler.cancelTask(callContext, "", "nonexistent"); - - Assertions.assertEquals(404, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("TaskNotFoundError")); - } - - @Test - public void testSendStreamingMessageSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - String requestBody = """ - { - "message": { - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me some jokes" - } - ], - "messageId": "message-1234", - "contextId": "context-1234" - }, - "configuration": { - "acceptedOutputModes": ["text"] - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); - Assertions.assertEquals(200, response.getStatusCode(), response.toString()); - Assertions.assertInstanceOf(RestHandler.HTTPRestStreamingResponse.class, response); - RestHandler.HTTPRestStreamingResponse streamingResponse = (RestHandler.HTTPRestStreamingResponse) response; - Assertions.assertNotNull(streamingResponse.getPublisher()); - Assertions.assertEquals("text/event-stream", streamingResponse.getContentType()); - } - - @Test - public void testSendStreamingMessageNotSupported() { - AgentCard card = createAgentCard(false, true); - RestHandler handler = new RestHandler(card, requestHandler, internalExecutor); - - String requestBody = """ - { - "contextId": "ctx123", - "role": "ROLE_USER", - "parts": [{ - "text": "Hello" - }] - } - """; - - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); - - Assertions.assertEquals(400, response.getStatusCode()); - Assertions.assertTrue(response.getBody().contains("InvalidRequestError")); - } - - @Test - public void testPushNotificationConfigSuccess() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - String requestBody = """ - { - "taskId": "%s", - "configId": "default-config-id", - "config": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - }""".formatted(MINIMAL_TASK.id()); - - RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id()); - - Assertions.assertEquals(201, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertNotNull(response.getBody()); - } - - @Test - public void testPushNotificationConfigNotSupported() { - AgentCard card = createAgentCard(true, false); - RestHandler handler = new RestHandler(card, requestHandler, internalExecutor); - - String requestBody = """ - { - "taskId": "%s", - "pushNotificationConfig": { - "url": "http://example.com" - } - } - """.formatted(MINIMAL_TASK.id()); - - RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", requestBody, MINIMAL_TASK.id()); - - Assertions.assertEquals(501, response.getStatusCode()); - Assertions.assertTrue(response.getBody().contains("PushNotificationNotSupportedError")); - } - - @Test - public void testGetPushNotificationConfig() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - // First, create a push notification config - String createRequestBody = """ - { - "taskId": "%s", - "configId": "default-config-id", - "config": { - "url": "https://example.com/callback", - "authentication": { - "scheme": "jwt" - } - } - }""".formatted(MINIMAL_TASK.id()); - RestHandler.HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(callContext, "", createRequestBody, MINIMAL_TASK.id()); - Assertions.assertEquals(201, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); - // Now get it - response = handler.getTaskPushNotificationConfiguration(callContext, "", MINIMAL_TASK.id(), "default-config-id"); - Assertions.assertEquals(200, response.getStatusCode(), response.toString()); - Assertions.assertEquals("application/json", response.getContentType()); - } - - @Test - public void testDeletePushNotificationConfig() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - RestHandler.HTTPRestResponse response = handler.deleteTaskPushNotificationConfiguration(callContext, "", MINIMAL_TASK.id(), "default-config-id"); - Assertions.assertEquals(204, response.getStatusCode()); - } - - @Test - public void testListPushNotificationConfigs() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - RestHandler.HTTPRestResponse response = handler.listTaskPushNotificationConfigurations(callContext, "", MINIMAL_TASK.id(), 0, ""); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertNotNull(response.getBody()); - } - - @Test - public void testHttpStatusCodeMapping() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - // Test 400 for invalid request - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", ""); - Assertions.assertEquals(400, response.getStatusCode()); - - // Test 404 for not found - response = handler.getTask(callContext, "", "nonexistent", 0); - Assertions.assertEquals(404, response.getStatusCode()); - } - - @Test - public void testStreamingDoesNotBlockMainThread() throws Exception { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - // Track if the main thread gets blocked during streaming - AtomicBoolean eventReceived = new AtomicBoolean(false); - CountDownLatch streamStarted = new CountDownLatch(1); - CountDownLatch eventProcessed = new CountDownLatch(1); - agentExecutorExecute = (context, agentEmitter) -> { - // Wait a bit to ensure the main thread continues - try { - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - agentEmitter.sendMessage(context.getMessage()); - }; - - String requestBody = """ - { - "message": { - "role": "ROLE_USER", - "parts": [ - { - "text": "tell me some jokes" - } - ], - "messageId": "message-1234", - "contextId": "context-1234" - }, - "configuration": { - "acceptedOutputModes": ["text"] - } - }"""; - - // Start streaming - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertInstanceOf(RestHandler.HTTPRestStreamingResponse.class, response); - - RestHandler.HTTPRestStreamingResponse streamingResponse = (RestHandler.HTTPRestStreamingResponse) response; - Flow.Publisher publisher = streamingResponse.getPublisher(); - publisher.subscribe(new Flow.Subscriber() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - streamStarted.countDown(); - subscription.request(1); - } - - @Override - public void onNext(String item) { - eventReceived.set(true); - eventProcessed.countDown(); - } - - @Override - public void onError(Throwable throwable) { - eventProcessed.countDown(); - } - - @Override - public void onComplete() { - eventProcessed.countDown(); - } - }); - - // The main thread should not be blocked - we should be able to continue immediately - Assertions.assertTrue(streamStarted.await(100, TimeUnit.MILLISECONDS), - "Streaming subscription should start quickly without blocking main thread"); - - // This proves the main thread is not blocked - we can do other work - // Simulate main thread doing other work - Thread.sleep(50); - - // Wait for the actual event processing to complete - Assertions.assertTrue(eventProcessed.await(2, TimeUnit.SECONDS), - "Event should be processed within reasonable time"); - - // Verify we received the event - Assertions.assertTrue(eventReceived.get(), "Should have received streaming event"); - } - - @Test - public void testExtensionSupportRequiredErrorOnSendMessage() { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("REST", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/test-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); - - String requestBody = """ - { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": {} - }, - "configuration": { - "blocking": true - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); - - Assertions.assertEquals(400, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("ExtensionSupportRequiredError")); - Assertions.assertTrue(response.getBody().contains("https://example.com/test-extension")); - } - - @Test - public void testExtensionSupportRequiredErrorOnSendStreamingMessage() { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("REST", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/streaming-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); - - String requestBody = """ - { - "message": { - "role": "ROLE_USER", - "parts": [{ - "text": "tell me some jokes" - }], - "messageId": "message-1234", - "contextId": "context-1234" - }, - "configuration": { - "acceptedOutputModes": ["text"] - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(callContext, "", requestBody); - - // Streaming responses embed errors in the stream with status 200 - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertInstanceOf(RestHandler.HTTPRestStreamingResponse.class, response); - - // Subscribe to publisher and verify error in stream - RestHandler.HTTPRestStreamingResponse streamingResponse = (RestHandler.HTTPRestStreamingResponse) response; - Flow.Publisher publisher = streamingResponse.getPublisher(); - - AtomicBoolean errorFound = new AtomicBoolean(false); - CountDownLatch latch = new CountDownLatch(1); - - publisher.subscribe(new Flow.Subscriber() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscription.request(1); - } - - @Override - public void onNext(String item) { - if (item.contains("ExtensionSupportRequiredError") && - item.contains("https://example.com/streaming-extension")) { - errorFound.set(true); - } - latch.countDown(); - } - - @Override - public void onError(Throwable throwable) { - latch.countDown(); - } - - @Override - public void onComplete() { - latch.countDown(); - } - }); - - try { - Assertions.assertTrue(latch.await(1, TimeUnit.SECONDS)); - Assertions.assertTrue(errorFound.get(), "Error should be found in streaming response"); - } catch (InterruptedException e) { - Assertions.fail("Test interrupted"); - } - } - - @Test - public void testRequiredExtensionProvidedSuccess() { - // Create AgentCard with a required extension - AgentCard cardWithExtension = AgentCard.builder() - .name("test-card") - .description("Test card with required extension") - .supportedInterfaces(Collections.singletonList(new AgentInterface("REST", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(true) - .extensions(List.of( - AgentExtension.builder() - .uri("https://example.com/required-extension") - .required(true) - .build() - )) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - RestHandler handler = new RestHandler(cardWithExtension, requestHandler, internalExecutor); - - // Create context WITH the required extension - Set requestedExtensions = new HashSet<>(); - requestedExtensions.add("https://example.com/required-extension"); - ServerCallContext contextWithExtension = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - requestedExtensions - ); - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - String requestBody = """ - { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": {} - }, - "configuration": { - "blocking": true - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithExtension, "", requestBody); - - // Should succeed without error - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertNotNull(response.getBody()); - } - - @Test - public void testVersionNotSupportedErrorOnSendMessage() { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("REST", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); - - // Create context with incompatible version 2.0 - ServerCallContext contextWithVersion = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - new HashSet<>(), - "2.0" // Incompatible version - ); - - String requestBody = """ - { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": {} - }, - "configuration": { - "blocking": true - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithVersion, "", requestBody); - - Assertions.assertEquals(501, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("VersionNotSupportedError")); - Assertions.assertTrue(response.getBody().contains("2.0")); - } - - @Test - public void testVersionNotSupportedErrorOnSendStreamingMessage() { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("REST", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); - - // Create context with incompatible version 2.0 - ServerCallContext contextWithVersion = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - new HashSet<>(), - "2.0" // Incompatible version - ); - - String requestBody = """ - { - "message": { - "role": "ROLE_USER", - "parts": [{ - "text": "tell me some jokes" - }], - "messageId": "message-1234", - "contextId": "context-1234" - }, - "configuration": { - "acceptedOutputModes": ["text"] - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendStreamingMessage(contextWithVersion, "", requestBody); - - // Streaming responses embed errors in the stream with status 200 - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertInstanceOf(RestHandler.HTTPRestStreamingResponse.class, response); - - // Subscribe to publisher and verify error in stream - RestHandler.HTTPRestStreamingResponse streamingResponse = (RestHandler.HTTPRestStreamingResponse) response; - Flow.Publisher publisher = streamingResponse.getPublisher(); - - AtomicBoolean errorFound = new AtomicBoolean(false); - CountDownLatch latch = new CountDownLatch(1); - - publisher.subscribe(new Flow.Subscriber<>() { - @Override - public void onSubscribe(Flow.Subscription subscription) { - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(String item) { - if (item.contains("VersionNotSupportedError") && - item.contains("2.0")) { - errorFound.set(true); - } - } - - @Override - public void onError(Throwable throwable) { - latch.countDown(); - } - - @Override - public void onComplete() { - latch.countDown(); - } - }); - - try { - Assertions.assertTrue(latch.await(1, TimeUnit.SECONDS)); - Assertions.assertTrue(errorFound.get(), "Error should be found in streaming response"); - } catch (InterruptedException e) { - Assertions.fail("Test interrupted"); - } - } - - @Test - public void testCompatibleVersionSuccess() { - // Create AgentCard with protocol version 1.0 - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("REST", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); - - // Create context with compatible version 1.1 - ServerCallContext contextWithVersion = new ServerCallContext( - UnauthenticatedUser.INSTANCE, - Map.of("foo", "bar"), - new HashSet<>(), - "1.1" // Compatible version (same major version) - ); - - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - String requestBody = """ - { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": {} - }, - "configuration": { - "blocking": true - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendMessage(contextWithVersion, "", requestBody); - - // Should succeed without error - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertNotNull(response.getBody()); - } - - @Test - public void testNoVersionDefaultsToCurrentVersionSuccess() { - // Create AgentCard with protocol version 1.0 (current version) - AgentCard agentCard = AgentCard.builder() - .name("test-card") - .description("Test card with version 1.0") - .supportedInterfaces(Collections.singletonList(new AgentInterface("REST", "http://localhost:9999"))) - .version("1.0.0") - .capabilities(AgentCapabilities.builder() - .streaming(true) - .pushNotifications(false) - .build()) - .defaultInputModes(List.of("text")) - .defaultOutputModes(List.of("text")) - .skills(List.of()) - .build(); - - RestHandler handler = new RestHandler(agentCard, requestHandler, internalExecutor); - - // Use default callContext (no version - should default to 1.0) - agentExecutorExecute = (context, agentEmitter) -> { - agentEmitter.sendMessage(context.getMessage()); - }; - - String requestBody = """ - { - "message": { - "messageId": "message-1234", - "contextId": "context-1234", - "role": "ROLE_USER", - "parts": [{ - "text": "tell me a joke" - }], - "metadata": {} - }, - "configuration": { - "blocking": true - } - }"""; - - RestHandler.HTTPRestResponse response = handler.sendMessage(callContext, "", requestBody); - - // Should succeed without error (defaults to 1.0) - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertNotNull(response.getBody()); - } - - @Test - public void testListTasksNegativeTimestampReturns422() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - // Negative timestamp should return 422 (Invalid params) - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, null, null, null, - null, "-1", null); - - Assertions.assertEquals(422, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains("InvalidParamsError")); - } - - @Test - public void testListTasksUnixMillisecondsTimestamp() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - // Unix milliseconds timestamp are no longer accepted - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, null, null, null, - null, "1234567", null); - Assertions.assertEquals(422, response.getStatusCode()); - } - - @Test - public void testListTasksProtobufEnumStatus() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - // Protobuf enum format (TASK_STATE_SUBMITTED) should be accepted - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "TASK_STATE_SUBMITTED", null, null, - null, null, null); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); - } - - @Test - public void testListTasksEnumConstantStatus() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - taskStore.save(MINIMAL_TASK, false); - - // Enum constant format (TASK_STATE_SUBMITTED) should be accepted - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", null, "TASK_STATE_SUBMITTED", null, null, - null, null, null); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - Assertions.assertTrue(response.getBody().contains(MINIMAL_TASK.id())); - } - - @Test - public void testListTasksEmptyResultIncludesAllFields() { - RestHandler handler = new RestHandler(CARD, requestHandler, internalExecutor); - - // Query for a context that doesn't exist - should return empty result with all fields - RestHandler.HTTPRestResponse response = handler.listTasks(callContext, "", "nonexistent-context-id", null, null, null, - null, null, null); - - Assertions.assertEquals(200, response.getStatusCode()); - Assertions.assertEquals("application/json", response.getContentType()); - - String body = response.getBody(); - // Verify all required fields are present (not missing) - Assertions.assertTrue(body.contains("\"tasks\""), "Response should contain tasks field"); - Assertions.assertTrue(body.contains("\"totalSize\""), "Response should contain totalSize field"); - Assertions.assertTrue(body.contains("\"pageSize\""), "Response should contain pageSize field"); - Assertions.assertTrue(body.contains("\"nextPageToken\""), "Response should contain nextPageToken field"); - // Verify empty array, not null - Assertions.assertTrue(body.contains("\"tasks\":[]") || body.contains("\"tasks\": []"), - "tasks should be empty array"); - } -} diff --git a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java b/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java deleted file mode 100644 index 68aad41bb..000000000 --- a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestTestTransportMetadata.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.a2a.transport.rest.handler; - -import io.a2a.server.TransportMetadata; -import io.a2a.spec.TransportProtocol; - -public class RestTestTransportMetadata implements TransportMetadata { - @Override - public String getTransportProtocol() { - return TransportProtocol.HTTP_JSON.asString(); - } - -} diff --git a/transport/rest/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata b/transport/rest/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata deleted file mode 100644 index 3604945b4..000000000 --- a/transport/rest/src/test/resources/META-INF/services/io.a2a.server.TransportMetadata +++ /dev/null @@ -1,2 +0,0 @@ -# Add a test TransportMetadata so we pass AgentCard validation -io.a2a.transport.rest.handler.RestTestTransportMetadata \ No newline at end of file diff --git a/transport/rest/src/test/resources/a2a-requesthandler-test.properties b/transport/rest/src/test/resources/a2a-requesthandler-test.properties deleted file mode 100644 index 33abcce34..000000000 --- a/transport/rest/src/test/resources/a2a-requesthandler-test.properties +++ /dev/null @@ -1 +0,0 @@ -preferred-transport=HTTP+JSON \ No newline at end of file diff --git a/update-version.sh b/update-version.sh deleted file mode 100755 index 8e7f3d9db..000000000 --- a/update-version.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/bin/bash - -# Update version across POMs and JBang scripts -# Usage: ./update-version.sh FROM_VERSION TO_VERSION [--dry-run] - -set -euo pipefail # Exit on error, unset var, and pipe failure - -FROM_VERSION=$1 -TO_VERSION=$2 - -# Validate arguments -if [ -z "$FROM_VERSION" ] || [ -z "$TO_VERSION" ]; then - echo "❌ Error: Missing version arguments." >&2 - echo "Usage: $0 FROM_VERSION TO_VERSION [--dry-run]" >&2 - echo "Example: $0 0.3.0.Beta1-SNAPSHOT 0.3.0.Beta1" >&2 - exit 1 -fi - -# Check if TO_VERSION looks like a flag -if [[ "$TO_VERSION" == --* ]]; then - echo "❌ Error: TO_VERSION cannot be a flag. Did you mean to provide both FROM_VERSION and TO_VERSION?" >&2 - echo "Usage: $0 FROM_VERSION TO_VERSION [--dry-run]" >&2 - echo "Example: $0 0.3.0.Beta1-SNAPSHOT 0.3.0.Beta1" >&2 - exit 1 -fi - -DRY_RUN=false -if [ "${3:-}" = "--dry-run" ]; then - DRY_RUN=true -elif [ -n "${3:-}" ]; then - echo "❌ Error: Invalid third argument. Only '--dry-run' is supported." >&2 - echo "Usage: $0 FROM_VERSION TO_VERSION [--dry-run]" >&2 - exit 1 -fi - -# Verify we're in the right directory -if [ ! -f "pom.xml" ]; then - echo "❌ Error: pom.xml not found. Run this script from the a2a-java root directory." >&2 - exit 1 -fi - -echo "🔍 Updating version from $FROM_VERSION → $TO_VERSION" -echo "" - -# Find all files to update -POM_FILES=$(find . -type f -name "pom.xml" | sort) -JBANG_FILES=$(find . -type f -name "*.java" -path "*/examples/*" -exec grep -l "//DEPS io.github.a2asdk:" {} \; | sort) - -POM_COUNT=$(echo "$POM_FILES" | wc -l | tr -d ' ') -JBANG_COUNT=$(echo "$JBANG_FILES" | wc -l | tr -d ' ') - -echo "📄 Found $POM_COUNT pom.xml files" -echo "📄 Found $JBANG_COUNT JBang script files" -echo "" - -# Show what will be changed -if [ "$DRY_RUN" = true ]; then - echo "🔎 DRY RUN - showing what would be changed:" - echo "" - - echo "=== POM files with version $FROM_VERSION ===" - for file in $POM_FILES; do - if grep -q "$FROM_VERSION" "$file"; then - echo " 📝 $file" - grep -n "$FROM_VERSION" "$file" | sed 's/^/ /' - fi - done - echo "" - - echo "=== JBang files with version $FROM_VERSION ===" - for file in $JBANG_FILES; do - if grep -q "//DEPS io.github.a2asdk:.*:$FROM_VERSION" "$file"; then - echo " 📝 $file" - grep -n "//DEPS io.github.a2asdk:.*:$FROM_VERSION" "$file" | sed 's/^/ /' - fi - done - echo "" - - echo "✅ Dry run complete. Run without --dry-run to apply changes." - exit 0 -fi - -# Perform actual updates -echo "🔄 Updating files..." -echo "" - -UPDATED_POMS=0 -UPDATED_JBANGS=0 - -# Update POM files -echo "Updating pom.xml files..." -for file in $POM_FILES; do - if grep -q "$FROM_VERSION" "$file"; then - if [[ "$OSTYPE" == "darwin"* ]]; then - # macOS requires empty string after -i - sed -i "" -e "s|>$FROM_VERSION<|>$TO_VERSION<|g" "$file" - else - # Linux doesn't need it - sed -i "s|>$FROM_VERSION<|>$TO_VERSION<|g" "$file" - fi - echo " ✅ $file" - UPDATED_POMS=$((UPDATED_POMS + 1)) - fi -done -echo "" - -# Update JBang files -echo "Updating JBang script files..." -for file in $JBANG_FILES; do - if grep -q "//DEPS io.github.a2asdk:.*:$FROM_VERSION" "$file"; then - if [[ "$OSTYPE" == "darwin"* ]]; then - # macOS requires empty string after -i - sed -i "" -e "s/\(\/\/DEPS io.github.a2asdk:.*:\)$FROM_VERSION/\1$TO_VERSION/g" "$file" - else - # Linux doesn't need it - sed -i "s/\(\/\/DEPS io.github.a2asdk:.*:\)$FROM_VERSION/\1$TO_VERSION/g" "$file" - fi - echo " ✅ $file" - UPDATED_JBANGS=$((UPDATED_JBANGS + 1)) - fi -done -echo "" - -# Summary -echo "✅ Version update complete!" -echo " Updated $UPDATED_POMS pom.xml files" -echo " Updated $UPDATED_JBANGS JBang script files" -echo "" -echo "📋 Next steps:" -echo " 1. Review changes: git diff" -echo " 2. Verify build: mvn clean install" -echo " 3. Commit changes: git commit -am 'chore: release $TO_VERSION'"