diff --git a/.github/workflows/deploy-site.yml b/.github/workflows/deploy-site.yml new file mode 100644 index 000000000..bab6c5147 --- /dev/null +++ b/.github/workflows/deploy-site.yml @@ -0,0 +1,32 @@ +name: Roq Site Deploy + +on: + push: + branches: [ main ] # Switch to the branch which should be deployed to GitHub Pages + paths: + - docs/** + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Generate Roq Site + uses: quarkiverse/quarkus-roq@v1.1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} # Used to automatically get the GitHub Pages url + site-directory: ./docs/ + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + permissions: + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..ab02d8bdf --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,48 @@ +#Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +release.properties +.flattened-pom.xml + +# Eclipse +.project +.classpath +.settings/ +bin/ + +# IntelliJ +.idea +*.ipr +*.iml +*.iws + +# NetBeans +nb-configuration.xml + +# Visual Studio Code +.vscode +.factorypath + +# OSX +.DS_Store + +# Vim +*.swp +*.swo + +# patch +*.orig +*.rej + +# Local environment +.env + +# Plugin directory +/.quarkus/cli/plugins/ +# TLS Certificates +.certs/ + +# Web Bundler +node_modules/ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..1d6879d82 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,66 @@ + +# A2A Java SDK Documentation + +A static site built with [Roq](https://iamroq.dev), a static site generator powered by Quarkus. + +## Getting Started + +Install the [Roq CLI](https://iamroq.dev/docs/getting-started/) (installs [JBang](https://www.jbang.dev/download) if needed): +```bash +curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force roq@quarkiverse/quarkus-roq +``` + +Then: +```bash +# Start dev mode with live-reload +roq start + +# Build the static site +roq generate + +# Preview the generated site +roq serve +``` + +Dev mode runs on http://localhost:8080 (use `-p` to change the port). + +## Project Structure + +``` +content/ Pages and collections (posts/, etc.) +templates/ + layouts/ Page layouts + partials/ Reusable template fragments +data/ Structured data files (YAML/JSON) +public/ Static assets served as-is (images, etc.) +web/ JS/CSS sources (bundled by Quarkus Web Bundler) +config/ + application.properties +``` + +## Useful Commands + +```bash +roq add plugin:tagging # Add a plugin +roq add theme:default # Add a theme +roq update # Update to latest Roq version +``` + +## AI Coding Assistants + +Give your AI assistant full context about Roq by pointing it to https://iamroq.dev/llms.txt. + +For detailed skill files, run: +```bash +mvn dependency:list -DincludeGroupIds=io.quarkiverse.roq -DoutputAbsoluteArtifactFilename=true +``` +Then extract skills from the `*-deployment` JARs listed in the output: +```bash +unzip -p PATH_TO_JAR META-INF/quarkus-skill.md > .claude/skills/SKILL_NAME.md +``` + +## Learn More + +- [Roq Documentation](https://iamroq.dev/docs/) +- [Qute Template Reference](https://quarkus.io/guides/qute-reference) +- [Quarkus](https://quarkus.io/) diff --git a/docs/content/404.html b/docs/content/404.html new file mode 100644 index 000000000..a62d0f108 --- /dev/null +++ b/docs/content/404.html @@ -0,0 +1,4 @@ +--- +layout: 404 +image: logo.svg +--- diff --git a/docs/content/about.md b/docs/content/about.md new file mode 100644 index 000000000..b7ffc9c1a --- /dev/null +++ b/docs/content/about.md @@ -0,0 +1,19 @@ +--- +title: About +description: A static site generator built with Java and Quarkus. Zero config to get started, full power of the JVM when you need it. +layout: page +--- + +# About this site + +This site is built with [Roq](https://iamroq.dev), a static site generator powered by [Quarkus](https://quarkus.io). It combines the best of tools like Jekyll and Hugo with the Java ecosystem: zero configuration to get started, blazing fast live-reload in dev mode, and full access to Java when you need it. + +## Authors + +
+ {#for id in cdi:authors.fields} + {#let author=cdi:authors.get(id)} + {#roq/authorCard name=author.name avatar=author.avatar?? nickname=author.nickname profile=author.profile /} + {/for} +
+ diff --git a/docs/content/announces.html b/docs/content/announces.html new file mode 100644 index 000000000..1f80efa4c --- /dev/null +++ b/docs/content/announces.html @@ -0,0 +1,8 @@ +--- +title: Announcements +description: Release announcements and news from the A2A Java SDK project. +layout: blog +paginate: + collection: posts + size: 10 +--- diff --git a/docs/content/client.md b/docs/content/client.md new file mode 100644 index 000000000..7083ac2a4 --- /dev/null +++ b/docs/content/client.md @@ -0,0 +1,210 @@ +--- +title: A2A Client Guide +description: Communicate with A2A-compliant agents using the A2A Java SDK client. +layout: page +--- + +# A2A Client + +The A2A Java SDK provides a Java client for communicating with any A2A-compliant agent. Supports JSON-RPC 2.0, gRPC, and HTTP+JSON/REST transports. + +## 1. Add the Client Dependency + +```xml + + org.a2aproject.sdk + a2a-java-sdk-client + + $\{org.a2aproject.sdk.version} + +``` + +The client artifact includes the JSON-RPC transport by default. For gRPC or REST, add the corresponding transport: + +```xml + + + org.a2aproject.sdk + a2a-java-sdk-client-transport-grpc + $\{org.a2aproject.sdk.version} + + + + + org.a2aproject.sdk + a2a-java-sdk-client-transport-rest + $\{org.a2aproject.sdk.version} + +``` + +## 2. Create a Client + +```java +// Resolve the agent card from the server +AgentCard agentCard = A2ACardResolver.builder() + .baseUrl("http://localhost:1234") + .build() + .getAgentCard(); + +// Configure accepted output modes +ClientConfig clientConfig = new ClientConfig.Builder() + .setAcceptedOutputModes(List.of("text")) + .build(); + +// Define event consumers +List> consumers = List.of( + (event, card) -> { + if (event instanceof MessageEvent messageEvent) { + // handle message + } else if (event instanceof TaskEvent taskEvent) { + // handle task + } else if (event instanceof TaskUpdateEvent updateEvent) { + // handle task update + } + } +); + +// Build the client +Client client = Client + .builder(agentCard) + .clientConfig(clientConfig) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) + .addConsumers(consumers) + .streamingErrorHandler(error -> { /* handle errors */ }) + .build(); +``` + +## 3. Send Messages + +```java +// Send a text message (streaming used automatically if supported) +Message message = A2A.toUserMessage("tell me a joke"); +client.sendMessage(message); + +// Send with per-call custom consumers +client.sendMessage(message, customConsumers, customErrorHandler); + +// Send with a call context +client.sendMessage(message, clientCallContext); +``` + +## Task Management + +```java +// Get task state +Task task = client.getTask(new TaskQueryParams("task-1234")); +Task task = client.getTask(new TaskQueryParams("task-1234", 10)); // with history limit + +// Cancel a task +Task cancelled = client.cancelTask(new TaskIdParams("task-1234")); + +// Subscribe to an ongoing task +client.subscribeToTask(new TaskIdParams("task-1234")); +client.subscribeToTask(taskIdParams, customConsumers, customErrorHandler); + +// Retrieve the server agent card +AgentCard serverCard = client.getAgentCard(); +``` + +## Push Notifications + +```java +// Set a push notification configuration +PushNotificationConfig pushConfig = PushNotificationConfig.builder() + .url("https://example.com/callback") + .authenticationInfo(new AuthenticationInfo(List.of("jwt"), null)) + .build(); + +TaskPushNotificationConfig taskConfig = TaskPushNotificationConfig.builder() + .taskId("task-1234") + .pushNotificationConfig(pushConfig) + .build(); + +client.createTaskPushNotificationConfiguration(taskConfig); + +// List configurations +List configs = + client.listTaskPushNotificationConfigurations( + new ListTaskPushNotificationConfigParams("task-1234")); + +// Delete a configuration +client.deleteTaskPushNotificationConfigurations( + new DeleteTaskPushNotificationConfigParams("task-1234", "config-4567")); +``` + +## Transport Configuration + +### JSON-RPC with a Custom HTTP Client + +```java +// Use a custom JDK HTTP client +HttpClient jdkHttpClient = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(5)) + .followRedirects(HttpClient.Redirect.NORMAL) + .build(); + +Client client = Client + .builder(agentCard) + .withTransport(JSONRPCTransport.class, + new JSONRPCTransportConfig(new JdkA2AHttpClient(jdkHttpClient))) + .build(); +``` + +### gRPC + +```java +Function channelFactory = agentUrl -> + ManagedChannelBuilder.forTarget(agentUrl).build(); + +Client client = Client + .builder(agentCard) + .withTransport(GrpcTransport.class, new GrpcTransportConfig(channelFactory)) + .build(); +``` + +### Multiple Transports + +```java +Client client = Client + .builder(agentCard) + .withTransport(GrpcTransport.class, new GrpcTransportConfig(channelFactory)) + .withTransport(JSONRPCTransport.class, new JSONRPCTransportConfig()) + .withTransport(RestTransport.class, new RestTransportConfig()) + .build(); +``` + +## Communicating with v0.3 Agents + +Use `Client_v0_3` to communicate with agents that only support protocol v0.3: + +```xml + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client + $\{org.a2aproject.sdk.version} + + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-client-transport-jsonrpc + $\{org.a2aproject.sdk.version} + +``` + +```java +AgentCard card = A2ACardResolver.builder().baseUrl("http://localhost:1234") + .build().getAgentCard(); + +AgentInterface v03Interface = card.supportedInterfaces().stream() + .filter(i -> A2AProtocol_v0_3.PROTOCOL_VERSION.equals(i.protocolVersion())) + .findFirst().orElseThrow(); + +Client_v0_3 client = ClientBuilder_v0_3.forUrl(v03Interface.url()) + .withTransport(JSONRPCTransport_v0_3.class, new JSONRPCTransportConfigBuilder_v0_3()) + .build(); +``` + +## Examples + +- [Hello World Client](https://github.com/a2aproject/a2a-java/blob/main/examples/helloworld/client/README.md) — Java client talking to a Python A2A server +- [Hello World Server](https://github.com/a2aproject/a2a-java/blob/main/examples/helloworld/server/README.md) — Python client talking to a Java A2A server +- [a2a-samples repository](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents) — More agent examples diff --git a/docs/content/community.md b/docs/content/community.md new file mode 100644 index 000000000..48eea5110 --- /dev/null +++ b/docs/content/community.md @@ -0,0 +1,50 @@ +--- +title: Community Articles +description: Articles, blog posts, and videos from the A2A Java SDK community. +layout: page +--- + +# Community Articles + +## 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 the 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. Also on [Medium](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. Also on [Medium](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. Also on [Medium](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. Also on [Medium](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. + +- [Getting Started with A2A Java SDK and gRPC](https://quarkus.io/blog/quarkus-a2a-java-grpc/) — Learn how to create an A2A server agent and client communicating over gRPC. Also on [Medium](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/) — Secure an A2A server agent using OAuth2 bearer tokens via Keycloak. + +- [How to Use Your A2A Server Agent in a Distributed or Cloud Native Environment](https://quarkus.io/blog/quarkus-a2a-cloud-enhancements/) — Running A2A server agents reliably in load-balanced Kubernetes deployments. + +- [A2A Java SDK 1.0.0.Alpha1 — Embracing the 1.0 Specification](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha1/) — Aligning the SDK with the 1.0 version of the A2A Protocol specification. + +- [A2A Java SDK 1.0.0.Alpha2 Released](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha2-released/) — Telemetry support and push notifications. + +- [A2A Java SDK 1.0.0.Beta1 Released](https://quarkus.io/blog/a2a-java-sdk-1-0-0-beta1-released/) — First beta, fully aligned with A2A Specification 1.0.0. + +- [A2A Java SDK 1.0.0.CR1 Released](https://quarkus.io/blog/a2a-java-sdk-1-0-0-cr1-released/) — v0.3 compatibility layer, Android HTTP client, unified HTTP clients. + +## A2A Java SDK for Jakarta Servers + +- [Building your First A2A Agent](https://www.wildfly.org/news/2025/08/07/Building-your-First-A2A-Agent/) — Introduction to the A2A Java SDK for Jakarta Servers with WildFly. + +- [A2A Java SDK for Jakarta 0.3.0.Beta1 is released!](https://www.wildfly.org/news/2025/09/19/A2A-Java-SDK-for-Jakarta-0-3-0-Beta1-is-released/) — gRPC and HTTP+JSON transport support for WildFly. + +- [A2A Java SDK for Jakarta 0.3.0.Final is released!](https://www.wildfly.org/news/2025/11/06/A2A-Java-SDK-for-Jakarta-0-3-0-Final-is-released/) — Supporting version 0.3.0 of the A2A Protocol Specification. + +- [A2A Java SDK for Jakarta 1.0.0.Alpha1 is released!](https://www.wildfly.org/news/2026/01/20/A2A-Java-SDK-for-Jakarta-1-0-0-Alpha1-is-released/) — Supporting version 1.0 of the A2A Protocol Specification. diff --git a/docs/content/contributing.md b/docs/content/contributing.md new file mode 100644 index 000000000..fa027884a --- /dev/null +++ b/docs/content/contributing.md @@ -0,0 +1,87 @@ +--- +title: Contributing +description: Developer guide for contributing to the A2A Java SDK. +layout: page +--- + +# Contributing + +See [CONTRIBUTING.md](https://github.com/a2aproject/a2a-java/blob/main/CONTRIBUTING.md) for full contribution guidelines. Fork the repo, create a branch per issue, and submit PRs against `main`. + +## Build + +Requires Java 17+. Tests output is redirected to files by default. + +```bash +mvn clean install +``` + +## Project Structure + +| Module | Purpose | +|--------|---------| +| `spec/` | A2A specification types (Java records for the protocol) | +| `spec-grpc/` | gRPC protobuf definitions and generated classes | +| `common/` | Shared utilities | +| `client/base/` | Core client API | +| `client/transport/spi/` | Transport SPI | +| `client/transport/jsonrpc/`, `grpc/`, `rest/` | Transport implementations | +| `server-common/` | Server-side core (AgentExecutor, TaskStore, QueueManager) | +| `transport/` | Server transport layer | +| `reference/` | Reference server implementations (Quarkus) | +| `tck/` | Technology Compatibility Kit | +| `extras/` | Optional add-ons (OpenTelemetry, JPA stores, Kafka queue, Vert.x, Android) | +| `compat-0.3/` | Backward compatibility layer for A2A protocol v0.3 | +| `boms/` | Bill of Materials POMs | +| `examples/` | Sample applications | + +## Code Conventions + +- Package root: `org.a2aproject.sdk` +- Serialization: Gson +- Null safety: NullAway + JSpecify annotations via Error Prone +- Reference server runtime: Quarkus +- Testing: JUnit 5, Mockito, REST Assured, Testcontainers + +### Style + +- Sort import statements +- No star imports (e.g. `import java.util.*`) +- Use Java `record` for immutable data types +- Use `@Nullable` (from `org.jspecify.annotations`) for optional fields +- Use `org.a2aproject.sdk.util.Assert.checkNotNullParam()` in compact constructors +- Use `List.copyOf()` and `Map.copyOf()` for defensive copying +- Apply the Builder pattern for records with many fields (see `AgentCard.java`) + +### gRPC Regeneration + +Copy `a2a.proto` from upstream and adjust the `java_package` option: + +``` +option java_package = "org.a2aproject.sdk.grpc"; +``` + +Then regenerate: + +```bash +mvn clean install -Dskip.protobuf.generate=false -pl spec-grpc +``` + +## Commit Messages + +Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/): + +``` +feat: add streaming support for REST transport +fix: handle null task in cancelTask flow +chore: bump quarkus to 3.x +``` + +If the commit relates to a GitHub issue, add `This fixes #` at the end of the commit body. + +## Architecture Deep Dives + +Detailed architecture documentation lives in `.claude/architecture/`: + +- **EventQueue & Event Processing** — Queue lifecycle, request flows, usage scenarios +- **0.3 Compatibility Layer** — How v0.3 requests are converted to v1.0 internally diff --git a/docs/content/index.html b/docs/content/index.html new file mode 100644 index 000000000..40bfdaaa1 --- /dev/null +++ b/docs/content/index.html @@ -0,0 +1,49 @@ +--- +title: A2A Java SDK Documentation +description: A Java library that helps run agentic applications as A2A servers following the Agent2Agent (A2A) Protocol. +name: A2A Java SDK Documentation +simple-name: A2A Java SDK +image: a2a-java-sdk.png +social-github: a2aproject/a2a-java +layout: home +--- + + +{#roq/hero logo="/images/a2a-java-sdk.png"} + {#title}A2A Java SDK{/title} + {#tagline}Implement the Agent2Agent Protocol in Java{/tagline} + {#subtitle}A multi-module Maven library providing client and server support for A2A agent communication over JSON-RPC, gRPC, and REST transports.{/subtitle} + Server Guide + Client Guide +{/} + +
+ {#roq/featureCard icon="fa-server" title="A2A Server"} + Run your agentic Java application as an A2A server. Implement AgentExecutor and let the SDK handle protocol, routing, and streaming. + {/} + {#roq/featureCard icon="fa-plug" title="A2A Client"} + Communicate with any A2A-compliant agent. Supports streaming, push notifications, and task lifecycle management out of the box. + {/} + {#roq/featureCard icon="fa-network-wired" title="Multiple Transports"} + JSON-RPC 2.0, gRPC, and HTTP+JSON/REST transports — pick what fits your stack, or support them all simultaneously. + {/} + {#roq/featureCard icon="fa-code-branch" title="Protocol Compatibility"} + Serve v1.0 and v0.3 clients side-by-side with zero changes to your AgentExecutor. The compat layer handles conversion automatically. + {/} +
+ +
+

Quick Install

+

Add the A2A Java SDK reference server for JSON-RPC to your Maven project:

+ +```xml + + org.a2aproject.sdk + a2a-java-sdk-reference-jsonrpc + $\{org.a2aproject.sdk.version} + +``` + +

See the Server Guide and Client Guide for full setup instructions, or browse Community Articles for tutorials and examples.

+
+ diff --git a/docs/content/posts/2026-06-10-a2a-java-sdk-1-0-0-final-released/annouce.png b/docs/content/posts/2026-06-10-a2a-java-sdk-1-0-0-final-released/annouce.png new file mode 100644 index 000000000..b62caa5f9 Binary files /dev/null and b/docs/content/posts/2026-06-10-a2a-java-sdk-1-0-0-final-released/annouce.png differ diff --git a/docs/content/posts/2026-06-10-a2a-java-sdk-1-0-0-final-released/index.md b/docs/content/posts/2026-06-10-a2a-java-sdk-1-0-0-final-released/index.md new file mode 100644 index 000000000..2a877f6fd --- /dev/null +++ b/docs/content/posts/2026-06-10-a2a-java-sdk-1-0-0-final-released/index.md @@ -0,0 +1,134 @@ +--- +layout: post +title: 'A2A Java SDK 1.0.0.Final Released' +date: 2026-06-10 +tags: ai a2a +synopsis: 'A2A Java SDK 1.0.0.Final is now available -- the first GA release of the official Java SDK for the A2A Protocol.' +author: kkhan +--- + +![A2A Java SDK 1.0.0.Final announcement](annouce.png) + +I am pleased to announce the release of [A2A Java SDK 1.0.0.Final](https://github.com/a2aproject/a2a-java/releases/tag/v1.0.0.Final) -- our first GA release. The A2A Java SDK is the official Java implementation of the [Agent2Agent (A2A) Protocol](https://a2a-protocol.org/v1.0.0/specification/), an open standard that enables AI agents to communicate and collaborate regardless of underlying framework, language, or vendor. + +This release is the result of six months and seven pre-releases (four Alphas, a Beta, and a Candidate Release), with contributions from 17 people. If you've been tracking the pre-releases, you can upgrade from CR1 with no breaking changes. + +## What's A2A? + +The Agent2Agent (A2A) Protocol is an open standard, governed by the Linux Foundation, that lets AI agents discover each other's capabilities, delegate tasks, and collaborate -- even if they're written in different languages or built on different frameworks. For example, an orchestrator agent written in Python can delegate to a specialist agent written in Java. + +The A2A Java SDK provides everything you need to build A2A server agents and clients in Java, with reference implementations based on [Quarkus](https://quarkus.io) and community integration with [WildFly/Jakarta EE](https://github.com/wildfly-extras/a2a-jakarta). + +## Installation + +Import the BOM and add the dependencies for your chosen transport: + +```xml + + + + org.a2aproject.sdk + a2a-java-sdk-bom + 1.0.0.Final + pom + import + + + + + + + org.a2aproject.sdk + a2a-java-sdk-reference-jsonrpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-grpc + + + org.a2aproject.sdk + a2a-java-sdk-reference-rest + +``` + +All three transports -- JSON-RPC, gRPC, and HTTP+JSON/REST -- are fully supported and considered equal. Just pick the artifact(s) for the transport(s) you need. + +## What's New Since 1.0.0.CR1 + +[1.0.0.CR1](https://github.com/a2aproject/a2a-java/releases/tag/v1.0.0.CR1) was our feature-complete candidate release. Since then, we focused on cross-SDK interoperability validation and bug fixes. + +### Integration Test Kit (ITK) + +The biggest addition is the Integration Test Kit (ITK) -- a configurable Quarkus-based A2A agent that runs predefined scenarios from the ITK test harness to validate protocol compliance across different SDK implementations (Java, Python, TypeScript, etc.). This gives us confidence that the Java SDK interoperates correctly with agents built using other A2A SDKs. + +### Protocol Compliance and Stability Fixes + +Driven by ITK testing, we addressed several protocol compliance issues: + +* Fixed SSE event listener, gRPC blocking offload handling, and JSON-RPC route consistency across all transports +* Prevented dropped SSE events under back-to-back emission +* Propagated CDI request context correctly to `AgentExecutor` threads and streaming requests +* Improved `A2ACardResolver` to support complete agent card URLs +* Completed the records migration for v0.3 compatibility spec classes + +## The Journey from 0.3 to 1.0 + +The 0.3.x series was our first production-quality SDK, supporting JSON-RPC, gRPC, REST transports, security with OAuth2/Keycloak, and cloud-native deployment with persistent stores and replicated queues. The 1.0 series modernized the SDK to align with the final A2A Specification 1.0.0. + +Here is a summary of the major changes. Each of our previous blog posts covers its respective release in detail: + +### Specification and API + +* **A2A Protocol 1.0 alignment** -- the SDK implements the final [A2A Specification 1.0.0](https://a2a-protocol.org/v1.0.0/specification/), including the new `supportedInterfaces` model for `AgentCard`, removal of `kind` discriminators, and refined error handling ([Alpha1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha1/)) +* **Java records throughout** -- all spec domain classes are now Java records, providing immutability, consistent accessor naming (`card.name()` instead of `card.getName()`), and less boilerplate ([Alpha1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha1/)) +* **AgentEmitter API** -- replaced the `EventQueue` + `TaskUpdater` combination with a streamlined `AgentEmitter` interface for agent interactions ([Alpha2](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha2-released/)) +* **Structured error codes** -- A2A error types now carry structured codes and details for precise error handling ([Beta1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-beta1-released/)) + +### Server Architecture + +* **MainEventBus architecture** -- the server internals were rearchitected around a central event bus. Previously, event processing was driven directly by client requests. Now all events flow through a single-threaded `MainEventBusProcessor` that persists events to the `TaskStore` _before_ distributing them to clients. This guarantees clients never see unpersisted events, eliminates race conditions in concurrent task updates, and enables patterns like fire-and-forget tasks and late client reconnections ([Alpha2](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha2-released/)) + +### Infrastructure + +* **New coordinates** -- Maven `groupId` changed to `org.a2aproject.sdk` and Java packages renamed to `org.a2aproject.sdk.*`, reflecting the project's home under the [A2A Project organization](https://github.com/a2aproject) ([Beta1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-beta1-released/)) +* **Protobuf as source of truth** -- replaced Jackson with Gson and established `a2a.proto` as the authoritative definition, with MapStruct mappers giving compile errors if spec and proto diverge ([Alpha1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha1/)) +* **Maven BOMs** -- three BOMs (`a2a-java-sdk-bom`, `a2a-java-extras-bom`, `a2a-java-reference-bom`) for dependency management ([Alpha1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha1/)) + +### Capabilities + +* **OpenTelemetry telemetry** -- built-in tracing and monitoring for both client and server ([1.0.0.Alpha2](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha2-released/)) +* **Push notifications** -- full server and client support per the A2A 1.0 spec ([1.0.0.Alpha2](https://quarkus.io/blog/a2a-java-sdk-1-0-0-alpha2-released/)) +* **v0.3 backward compatibility** -- a compatibility layer that lets v1.0 agents interoperate with v0.3 agents and clients across all three transports, with multi-version convenience modules for serving both protocol versions simultaneously ([1.0.0.CR1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-cr1-released/)) +* **Android HTTP client** -- `AndroidA2AHttpClient` using `HttpURLConnection` makes the SDK usable on Android ([1.0.0.CR1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-cr1-released/)) +* **Spec-compliant SSE parser** -- a robust `ServerSentEvent` record with full SSE spec compliance ([1.0.0.CR1](https://quarkus.io/blog/a2a-java-sdk-1-0-0-cr1-released/)) + +### Quality + +* **JSpecify null-safety annotations** throughout the spec module +* **Comprehensive Javadoc** on all public API classes +* **TCK conformance** across all three transports for both v1.0 and v0.3 protocols +* **ITK cross-SDK interoperability testing** (Final) + +## Contributors + +The 1.0.0 series had 17 contributors across all pre-releases. Thank you all for your code, reviews, and feedback! + +[@brucearctor](https://github.com/brucearctor), [@CharlieZhang1999](https://github.com/CharlieZhang1999), [@dwieliczko](https://github.com/dwieliczko), [@ehsavoie](https://github.com/ehsavoie), [@HarshaRamesh11](https://github.com/HarshaRamesh11), [@jmesnil](https://github.com/jmesnil), [@kabir](https://github.com/kabir), [@Lirons01](https://github.com/Lirons01), [@LiZongbo](https://github.com/LiZongbo), [@luke-j-smith](https://github.com/luke-j-smith), [@maff](https://github.com/maff), [@neo1027144-creator](https://github.com/neo1027144-creator), [@pratik3558](https://github.com/pratik3558), [@RainYuY](https://github.com/RainYuY), [@sherryfox](https://github.com/sherryfox), [@tsabau](https://github.com/tsabau), [@yyy9942](https://github.com/yyy9942) + +## Resources + +* [Release Notes on GitHub](https://github.com/a2aproject/a2a-java/releases/tag/v1.0.0.Final) +* [Maven Central](https://central.sonatype.com/artifact/org.a2aproject.sdk/a2a-java-sdk-parent/1.0.0.Final) +* [JavaDoc](https://javadoc.io/doc/org.a2aproject.sdk/) +* [A2A Specification](https://a2a-protocol.org/v1.0.0/specification/) +* [Examples](https://github.com/a2aproject/a2a-java/tree/main/examples) + +## Come Join Us + +We value your feedback a lot so please report bugs, ask for improvements etc. Let's build something great together! + +If you are an A2A Java SDK user or just curious, don't be shy and join our welcoming community: + +* provide feedback on [GitHub](https://github.com/a2aproject/a2a-java/issues); +* craft some code and [push a PR](https://github.com/a2aproject/a2a-java/pulls); +* discuss with us in the `#a2a-java` channel on [Discord](https://discord.gg/jTtSkJB74Q); diff --git a/docs/content/server.md b/docs/content/server.md new file mode 100644 index 000000000..f74708820 --- /dev/null +++ b/docs/content/server.md @@ -0,0 +1,254 @@ +--- +title: A2A Server Guide +description: Run your agentic Java application as an A2A server following the Agent2Agent Protocol. +layout: page +--- + +# 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, follow the steps below. + +## Supported Transports + +- JSON-RPC 2.0 +- gRPC +- HTTP+JSON/REST + +## 1. Add a Server Dependency + +### JSON-RPC + +```xml + + org.a2aproject.sdk + a2a-java-sdk-reference-jsonrpc + + $\{org.a2aproject.sdk.version} + +``` + +### gRPC + +```xml + + org.a2aproject.sdk + a2a-java-sdk-reference-grpc + $\{org.a2aproject.sdk.version} + +``` + +### HTTP+JSON/REST + +```xml + + org.a2aproject.sdk + a2a-java-sdk-reference-rest + $\{org.a2aproject.sdk.version} + +``` + +You can add more than one transport dependency to support multiple protocols simultaneously. + +## 2. Define an Agent Card + +```java +@ApplicationScoped +public class WeatherAgentCardProducer { + + private static final String AGENT_URL = "http://localhost:10001"; + + @Produces + @PublicAgentCard + public AgentCard agentCard() { + return AgentCard.builder() + .name("Weather Agent") + .description("Helps with weather") + .supportedInterfaces(List.of( + new AgentInterface(TransportProtocol.JSONRPC.asString(), AGENT_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("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())) + .build(); + } +} +``` + +## 3. Implement an Agent Executor + +```java +@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 { + if (context.getTask() == null) { + agentEmitter.submit(); + } + agentEmitter.startWork(); + + String userMessage = extractTextFromMessage(context.getMessage()); + String response = weatherAgent.chat(userMessage); + + agentEmitter.addArtifact(List.of(new TextPart(response))); + agentEmitter.complete(); + } + + @Override + public void cancel(RequestContext context, AgentEmitter agentEmitter) throws JSONRPCError { + Task task = context.getTask(); + if (task == null) { + agentEmitter.cancel(); + return; + } + if (task.getStatus().state() == TaskState.CANCELED || + task.getStatus().state() == TaskState.COMPLETED) { + throw new TaskNotCancelableError(); + } + agentEmitter.cancel(); + } + + private String extractTextFromMessage(Message message) { + if (message == null) { + return ""; + } + StringBuilder textBuilder = new StringBuilder(); + for (Part part : message.parts()) { + if (part instanceof TextPart textPart) { + textBuilder.append(textPart.text()); + } + } + return textBuilder.toString(); + } + } +} +``` + +## 4. Configuration + +The SDK uses `META-INF/a2a-defaults.properties` for defaults. Override via `application.properties` when using Quarkus/MicroProfile Config: + +```properties +# Thread pool for async/streaming operations +a2a.executor.core-pool-size=5 +a2a.executor.max-pool-size=50 +a2a.executor.keep-alive-seconds=60 + +# Timeouts for blocking calls +a2a.blocking.agent.timeout.seconds=30 +a2a.blocking.consumption.timeout.seconds=5 +``` + +For LLM-based agents, increase `a2a.blocking.agent.timeout.seconds` to 60–120 seconds. + +## 5. Task Authorization (Optional) + +Implement `TaskAuthorizationProvider` to control per-user access: + +```java +@ApplicationScoped +public class MyTaskAuthorizationProvider implements TaskAuthorizationProvider { + + @Override + public boolean checkRead(ServerCallContext context, String taskId, TaskOperation op) { + return isOwner(context.getUser(), taskId); + } + + @Override + public boolean checkWrite(ServerCallContext context, String taskId, TaskOperation op) { + return isOwner(context.getUser(), taskId); + } + + @Override + public boolean checkCreate(ServerCallContext context, TaskOperation op) { + return context.getUser().isAuthenticated(); + } + + @Override + public boolean isTaskRecorded(String taskId) { + return ownershipStore.contains(taskId); + } + + @Override + public void recordOwnership(ServerCallContext context, String taskId, TaskOperation op) { + ownershipStore.put(taskId, context.getUser().getUsername()); + } +} +``` + +The SDK discovers the bean via CDI automatically — no additional wiring needed. + +| Operation | Authorization check | +|-----------|---------------------| +| `getTask`, `subscribeToTask`, `getTaskPushNotificationConfig`, `listTaskPushNotificationConfigs` | `checkRead` | +| `cancelTask`, `createTaskPushNotificationConfig`, `deleteTaskPushNotificationConfig` | `checkWrite` | +| `messageSend` / `messageSendStream` (existing task) | `checkWrite` | +| `messageSend` / `messageSendStream` (new task) | `checkCreate`, then `recordOwnership` | +| `listTasks` | `checkRead` per task | + +## Backward Compatibility with v0.3 + +Add compat modules alongside v1.0 modules to serve both protocol versions simultaneously. No changes to your `AgentExecutor` are needed. + +### Multi-Version Module (recommended) + +```xml + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-jsonrpc + $\{org.a2aproject.sdk.version} + + + + + org.a2aproject.sdk + a2a-java-sdk-reference-multiversion-rest + $\{org.a2aproject.sdk.version} + +``` + +### Individual Compat Modules + +```xml + + org.a2aproject.sdk + a2a-java-sdk-compat-0.3-reference-jsonrpc + $\{org.a2aproject.sdk.version} + +``` + +Version routing uses the `A2A-Version` HTTP header for JSON-RPC and REST; for gRPC it is implicit via protobuf package name. + +## Server Integrations + +- **Quarkus** — Reference implementations are Quarkus-based (JSON-RPC, gRPC, REST) +- **Jakarta EE** — [a2a-jakarta](https://github.com/wildfly-extras/a2a-jakarta) works with any Jakarta EE Web Profile runtime + +See [CONTRIBUTING_INTEGRATIONS.md](https://github.com/a2aproject/a2a-java/blob/main/CONTRIBUTING_INTEGRATIONS.md) to submit your own integration. diff --git a/docs/data/authors.yml b/docs/data/authors.yml new file mode 100644 index 000000000..1d6796acd --- /dev/null +++ b/docs/data/authors.yml @@ -0,0 +1,23 @@ +ehsavoie: + name: "Emmanuel Hugonnet" + nickname: "ehsavoie" + job: "Software Engineer" + bio: "Emmanuel works at Red Hat on WildFly Messaging integration. He currently works on the WildFly AI feature pack and support for Eclipse Che." + avatar: ehsavoie.png + twitter: "ehsavoie" + profile: "https://github.com/ehsavoie" +jmesnil: + name: "Jeff Mesnil" + nickname: "jmesnil" + job: "Software Engineer" + avatar: jmesnil.jpg + twitter: "jmesnil" + profile: "https://github.com/jmesnil" +kkhan: + name: "Kabir Khan" + nickname: "kkhan" + job: "Software Engineer" + bio: "Kabir started using JBoss back in 2000, and joined the team in 2004. Since then he has worked on JBoss AS/WildFly as a core developer." + avatar: kkhan.jpg + profile: "https://github.com/kabir" + diff --git a/docs/data/menu.yml b/docs/data/menu.yml new file mode 100644 index 000000000..f33b87e00 --- /dev/null +++ b/docs/data/menu.yml @@ -0,0 +1,37 @@ +items: + - title: "Home" + path: "/" + icon: "fa-solid fa-house" + - title: "Announcements" + path: "/announces" + icon: "fa-regular fa-newspaper" + - title: "Documentation" + type: "group" + icon: "fa-solid fa-book" + - title: "Server" + path: "/server" + icon: "fa-solid fa-server" + group: "documentation" + - title: "Client" + path: "/client" + icon: "fa-solid fa-plug" + group: "documentation" + - title: "Javadoc" + path: "https://javadoc.io/doc/org.a2aproject.sdk" + icon: "fa-solid fa-file-code" + group: "documentation" + target: "_blank" + - title: "Community" + path: "/community" + icon: "fa-solid fa-users" + - title: "Contributing" + path: "/contributing" + icon: "fa-solid fa-code-pull-request" + - title: "A2A Protocol" + path: "https://a2a-protocol.org/latest/" + icon: "fa-solid fa-arrow-up-right-from-square" + target: "_blank" + - title: "GitHub" + path: "https://github.com/a2aproject/a2a-java" + icon: "fa-brands fa-github" + target: "_blank" \ No newline at end of file diff --git a/docs/pom.xml b/docs/pom.xml new file mode 100644 index 000000000..9d500b8e5 --- /dev/null +++ b/docs/pom.xml @@ -0,0 +1,132 @@ + + + 4.0.0 + + + org.a2aproject.sdk + a2a-java-sdk-parent + 1.0.1.Final-SNAPSHOT + ../pom.xml + + + a2a-java-sdk-jsonrpc-common + quarkus + + + UTF-8 + true + + + + + + io.quarkus.platform + quarkus-bom + ${quarkus.platform.version} + pom + import + + + + + + + io.quarkiverse.roq + quarkus-roq + 2.1.4 + + + io.quarkiverse.roq + quarkus-roq-plugin-tagging + 2.1.4 + + + io.quarkiverse.roq + quarkus-roq-theme-default + 2.1.4 + + + io.quarkiverse.roq + quarkus-roq-plugin-markdown + 2.1.4 + + + io.quarkus + quarkus-arc + + + org.mvnpm + highlight.js + 11.11.1 + provided + + + org.mvnpm + highlightjs-copy + 1.0.6 + provided + + + io.quarkus + quarkus-junit + test + + + + + + + io.quarkus.platform + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + maven-surefire-plugin + + @{argLine} + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + maven-failsafe-plugin + ${maven-surefire-plugin.version} + + + + integration-test + verify + + + + + @{argLine} + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + native + + + + false + false + true + + + + diff --git a/docs/public/images/a2a-java-sdk.png b/docs/public/images/a2a-java-sdk.png new file mode 100644 index 000000000..5975f1c25 Binary files /dev/null and b/docs/public/images/a2a-java-sdk.png differ diff --git a/docs/public/images/apple-touch-icon.png b/docs/public/images/apple-touch-icon.png new file mode 100644 index 000000000..f00ce6a25 Binary files /dev/null and b/docs/public/images/apple-touch-icon.png differ diff --git a/docs/public/images/ehsavoie.png b/docs/public/images/ehsavoie.png new file mode 100755 index 000000000..f2a0bb64e Binary files /dev/null and b/docs/public/images/ehsavoie.png differ diff --git a/docs/public/images/favicon.ico b/docs/public/images/favicon.ico new file mode 100644 index 000000000..a6f2cddca Binary files /dev/null and b/docs/public/images/favicon.ico differ diff --git a/docs/public/images/favicon.svg b/docs/public/images/favicon.svg new file mode 100644 index 000000000..2e3295962 --- /dev/null +++ b/docs/public/images/favicon.svg @@ -0,0 +1,601 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + Print + + + 2026-04-06T10:23:28-04:00 + 2026-04-06T10:23:28-04:00 + 2026-04-06T10:23:28-04:00 + Adobe Illustrator 30.3 (Windows) + + + + 256 + 88 + JPEG + /9j/4AAQSkZJRgABAgEAAAAAAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAAAAAAAAEA AQAAAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAWAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AFX15eSz3l1qd4I/MTSyT cmaRZ4pYHosasF+DYSAJyH7HgM7mEIgARH7uvgb+/pv73lZSJJMj6/t2/B+x7FoEVreWtnDL5quo vMrwRyXNot5FI0cxQF0Ns6svwnqvGo8e+c5nJiSRjHh3seE8ve7rCBIAcZ467/0Mg0LVtS+vz6Jr IT9JW6CeC5iBWO5ti3H1QpJ4MrfC612NKbHMPPijwicPpO1dx7v1ORiySswl9Q+0Jy9zbRzxQPKi zzBjDEzAM4Shbip3PGu9MxxEkXWwbzIXSpkUuxVpnRWVWYBnNEBNCSATQfQMNLaDs9c0W+uprSzv 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 + + + + xmp.iid:b6fb7791-0f84-194d-b984-27338ba8ecf1 + xmp.did:b6fb7791-0f84-194d-b984-27338ba8ecf1 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + uuid:0deb1267-d6ad-4045-8509-fb22db3fa5d6 + xmp.did:526773d2-a98f-654f-bf01-cbbe9b3a6f9d + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:b6fb7791-0f84-194d-b984-27338ba8ecf1 + 2026-04-06T10:23:28-04:00 + Adobe Illustrator 30.3 (Windows) + / + + + + Print + AIRobin + True + False + False + 1 + + 199.066637 + 198.436679 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + CMYK Red + RGB + PROCESS + 237 + 28 + 36 + + + CMYK Yellow + RGB + PROCESS + 255 + 242 + 0 + + + CMYK Green + RGB + PROCESS + 0 + 166 + 81 + + + CMYK Cyan + RGB + PROCESS + 0 + 174 + 239 + + + CMYK Blue + RGB + PROCESS + 46 + 49 + 146 + + + CMYK Magenta + RGB + PROCESS + 236 + 0 + 140 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 190 + 30 + 45 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 239 + 65 + 54 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 241 + 90 + 41 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 247 + 148 + 29 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 251 + 176 + 64 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 249 + 237 + 50 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 215 + 223 + 35 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 141 + 198 + 63 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 57 + 181 + 74 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 0 + 148 + 68 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 0 + 104 + 56 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 43 + 182 + 115 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 0 + 167 + 157 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 39 + 170 + 225 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 28 + 117 + 188 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 43 + 57 + 144 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 38 + 34 + 98 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 102 + 45 + 145 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 146 + 39 + 143 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 158 + 31 + 99 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 218 + 28 + 92 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 238 + 42 + 123 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 194 + 181 + 155 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 155 + 133 + 121 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 114 + 102 + 88 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 89 + 74 + 66 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 196 + 154 + 108 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 169 + 124 + 80 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 139 + 94 + 60 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 117 + 76 + 41 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 96 + 57 + 19 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 60 + 36 + 21 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 65 + 64 + 66 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 113 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 130 + 133 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 147 + 149 + 152 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 167 + 169 + 172 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 188 + 190 + 192 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 209 + 211 + 212 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 242 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 237 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 242 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 222 + 23 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 33 + 64 + 154 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 152 + + + + + + + Adobe PDF library 18.00 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/public/images/jmesnil.jpg b/docs/public/images/jmesnil.jpg new file mode 100755 index 000000000..9a8c114a2 Binary files /dev/null and b/docs/public/images/jmesnil.jpg differ diff --git a/docs/public/images/kkhan.jpg b/docs/public/images/kkhan.jpg new file mode 100644 index 000000000..9033a0b53 Binary files /dev/null and b/docs/public/images/kkhan.jpg differ diff --git a/docs/public/images/logo.svg b/docs/public/images/logo.svg new file mode 100644 index 000000000..193e6302c --- /dev/null +++ b/docs/public/images/logo.svg @@ -0,0 +1,601 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + Print + + + 2026-04-06T10:23:28-04:00 + 2026-04-06T10:23:28-04:00 + 2026-04-06T10:23:28-04:00 + Adobe Illustrator 30.3 (Windows) + + + + 256 + 88 + JPEG + /9j/4AAQSkZJRgABAgEAAAAAAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAAAAAAAAEA AQAAAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAWAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AFX15eSz3l1qd4I/MTSyT cmaRZ4pYHosasF+DYSAJyH7HgM7mEIgARH7uvgb+/pv73lZSJJMj6/t2/B+x7FoEVreWtnDL5quo vMrwRyXNot5FI0cxQF0Ns6svwnqvGo8e+c5nJiSRjHh3seE8ve7rCBIAcZ467/0Mg0LVtS+vz6Jr IT9JW6CeC5iBWO5ti3H1QpJ4MrfC612NKbHMPPijwicPpO1dx7v1ORiySswl9Q+0Jy9zbRzxQPKi zzBjDEzAM4Shbip3PGu9MxxEkXWwbzIXSpkUuxVpnRWVWYBnNEBNCSATQfQMNLaDs9c0W+uprSzv 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 + + + + xmp.iid:b6fb7791-0f84-194d-b984-27338ba8ecf1 + xmp.did:b6fb7791-0f84-194d-b984-27338ba8ecf1 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + uuid:0deb1267-d6ad-4045-8509-fb22db3fa5d6 + xmp.did:526773d2-a98f-654f-bf01-cbbe9b3a6f9d + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:b6fb7791-0f84-194d-b984-27338ba8ecf1 + 2026-04-06T10:23:28-04:00 + Adobe Illustrator 30.3 (Windows) + / + + + + Print + AIRobin + True + False + False + 1 + + 199.066637 + 198.436679 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + CMYK Red + RGB + PROCESS + 237 + 28 + 36 + + + CMYK Yellow + RGB + PROCESS + 255 + 242 + 0 + + + CMYK Green + RGB + PROCESS + 0 + 166 + 81 + + + CMYK Cyan + RGB + PROCESS + 0 + 174 + 239 + + + CMYK Blue + RGB + PROCESS + 46 + 49 + 146 + + + CMYK Magenta + RGB + PROCESS + 236 + 0 + 140 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 190 + 30 + 45 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 239 + 65 + 54 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 241 + 90 + 41 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 247 + 148 + 29 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 251 + 176 + 64 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 249 + 237 + 50 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 215 + 223 + 35 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 141 + 198 + 63 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 57 + 181 + 74 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 0 + 148 + 68 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 0 + 104 + 56 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 43 + 182 + 115 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 0 + 167 + 157 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 39 + 170 + 225 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 28 + 117 + 188 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 43 + 57 + 144 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 38 + 34 + 98 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 102 + 45 + 145 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 146 + 39 + 143 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 158 + 31 + 99 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 218 + 28 + 92 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 238 + 42 + 123 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 194 + 181 + 155 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 155 + 133 + 121 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 114 + 102 + 88 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 89 + 74 + 66 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 196 + 154 + 108 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 169 + 124 + 80 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 139 + 94 + 60 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 117 + 76 + 41 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 96 + 57 + 19 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 60 + 36 + 21 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 65 + 64 + 66 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 113 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 130 + 133 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 147 + 149 + 152 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 167 + 169 + 172 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 188 + 190 + 192 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 209 + 211 + 212 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 242 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 237 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 242 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 222 + 23 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 33 + 64 + 154 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 152 + + + + + + + Adobe PDF library 18.00 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/public/images/mascot.svg b/docs/public/images/mascot.svg new file mode 100644 index 000000000..456fec120 --- /dev/null +++ b/docs/public/images/mascot.svg @@ -0,0 +1,616 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + Print + + + 2026-04-06T10:23:28-04:00 + 2026-04-06T10:23:28-04:00 + 2026-04-06T10:23:28-04:00 + Adobe Illustrator 30.3 (Windows) + + + + 256 + 88 + JPEG + /9j/4AAQSkZJRgABAgEAAAAAAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAAAAAAAAEA AQAAAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAWAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AFX15eSz3l1qd4I/MTSyT cmaRZ4pYHosasF+DYSAJyH7HgM7mEIgARH7uvgb+/pv73lZSJJMj6/t2/B+x7FoEVreWtnDL5quo vMrwRyXNot5FI0cxQF0Ns6svwnqvGo8e+c5nJiSRjHh3seE8ve7rCBIAcZ467/0Mg0LVtS+vz6Jr IT9JW6CeC5iBWO5ti3H1QpJ4MrfC612NKbHMPPijwicPpO1dx7v1ORiySswl9Q+0Jy9zbRzxQPKi zzBjDEzAM4Shbip3PGu9MxxEkXWwbzIXSpkUuxVpnRWVWYBnNEBNCSATQfQMNLaDs9c0W+uprSzv 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 + + + + xmp.iid:b6fb7791-0f84-194d-b984-27338ba8ecf1 + xmp.did:b6fb7791-0f84-194d-b984-27338ba8ecf1 + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + uuid:0deb1267-d6ad-4045-8509-fb22db3fa5d6 + xmp.did:526773d2-a98f-654f-bf01-cbbe9b3a6f9d + uuid:5D20892493BFDB11914A8590D31508C8 + proof:pdf + + + + + saved + xmp.iid:b6fb7791-0f84-194d-b984-27338ba8ecf1 + 2026-04-06T10:23:28-04:00 + Adobe Illustrator 30.3 (Windows) + / + + + + Print + AIRobin + True + False + False + 1 + + 199.066637 + 198.436679 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 35 + 31 + 32 + + + CMYK Red + RGB + PROCESS + 237 + 28 + 36 + + + CMYK Yellow + RGB + PROCESS + 255 + 242 + 0 + + + CMYK Green + RGB + PROCESS + 0 + 166 + 81 + + + CMYK Cyan + RGB + PROCESS + 0 + 174 + 239 + + + CMYK Blue + RGB + PROCESS + 46 + 49 + 146 + + + CMYK Magenta + RGB + PROCESS + 236 + 0 + 140 + + + C=15 M=100 Y=90 K=10 + RGB + PROCESS + 190 + 30 + 45 + + + C=0 M=90 Y=85 K=0 + RGB + PROCESS + 239 + 65 + 54 + + + C=0 M=80 Y=95 K=0 + RGB + PROCESS + 241 + 90 + 41 + + + C=0 M=50 Y=100 K=0 + RGB + PROCESS + 247 + 148 + 29 + + + C=0 M=35 Y=85 K=0 + RGB + PROCESS + 251 + 176 + 64 + + + C=5 M=0 Y=90 K=0 + RGB + PROCESS + 249 + 237 + 50 + + + C=20 M=0 Y=100 K=0 + RGB + PROCESS + 215 + 223 + 35 + + + C=50 M=0 Y=100 K=0 + RGB + PROCESS + 141 + 198 + 63 + + + C=75 M=0 Y=100 K=0 + RGB + PROCESS + 57 + 181 + 74 + + + C=85 M=10 Y=100 K=10 + RGB + PROCESS + 0 + 148 + 68 + + + C=90 M=30 Y=95 K=30 + RGB + PROCESS + 0 + 104 + 56 + + + C=75 M=0 Y=75 K=0 + RGB + PROCESS + 43 + 182 + 115 + + + C=80 M=10 Y=45 K=0 + RGB + PROCESS + 0 + 167 + 157 + + + C=70 M=15 Y=0 K=0 + RGB + PROCESS + 39 + 170 + 225 + + + C=85 M=50 Y=0 K=0 + RGB + PROCESS + 28 + 117 + 188 + + + C=100 M=95 Y=5 K=0 + RGB + PROCESS + 43 + 57 + 144 + + + C=100 M=100 Y=25 K=25 + RGB + PROCESS + 38 + 34 + 98 + + + C=75 M=100 Y=0 K=0 + RGB + PROCESS + 102 + 45 + 145 + + + C=50 M=100 Y=0 K=0 + RGB + PROCESS + 146 + 39 + 143 + + + C=35 M=100 Y=35 K=10 + RGB + PROCESS + 158 + 31 + 99 + + + C=10 M=100 Y=50 K=0 + RGB + PROCESS + 218 + 28 + 92 + + + C=0 M=95 Y=20 K=0 + RGB + PROCESS + 238 + 42 + 123 + + + C=25 M=25 Y=40 K=0 + RGB + PROCESS + 194 + 181 + 155 + + + C=40 M=45 Y=50 K=5 + RGB + PROCESS + 155 + 133 + 121 + + + C=50 M=50 Y=60 K=25 + RGB + PROCESS + 114 + 102 + 88 + + + C=55 M=60 Y=65 K=40 + RGB + PROCESS + 89 + 74 + 66 + + + C=25 M=40 Y=65 K=0 + RGB + PROCESS + 196 + 154 + 108 + + + C=30 M=50 Y=75 K=10 + RGB + PROCESS + 169 + 124 + 80 + + + C=35 M=60 Y=80 K=25 + RGB + PROCESS + 139 + 94 + 60 + + + C=40 M=65 Y=90 K=35 + RGB + PROCESS + 117 + 76 + 41 + + + C=40 M=70 Y=100 K=50 + RGB + PROCESS + 96 + 57 + 19 + + + C=50 M=70 Y=80 K=70 + RGB + PROCESS + 60 + 36 + 21 + + + + + + Grays + 1 + + + + C=0 M=0 Y=0 K=100 + RGB + PROCESS + 35 + 31 + 32 + + + C=0 M=0 Y=0 K=90 + RGB + PROCESS + 65 + 64 + 66 + + + C=0 M=0 Y=0 K=80 + RGB + PROCESS + 88 + 89 + 91 + + + C=0 M=0 Y=0 K=70 + RGB + PROCESS + 109 + 110 + 113 + + + C=0 M=0 Y=0 K=60 + RGB + PROCESS + 128 + 130 + 133 + + + C=0 M=0 Y=0 K=50 + RGB + PROCESS + 147 + 149 + 152 + + + C=0 M=0 Y=0 K=40 + RGB + PROCESS + 167 + 169 + 172 + + + C=0 M=0 Y=0 K=30 + RGB + PROCESS + 188 + 190 + 192 + + + C=0 M=0 Y=0 K=20 + RGB + PROCESS + 209 + 211 + 212 + + + C=0 M=0 Y=0 K=10 + RGB + PROCESS + 230 + 231 + 232 + + + C=0 M=0 Y=0 K=5 + RGB + PROCESS + 241 + 242 + 242 + + + + + + Brights + 1 + + + + C=0 M=100 Y=100 K=0 + RGB + PROCESS + 237 + 28 + 36 + + + C=0 M=75 Y=100 K=0 + RGB + PROCESS + 242 + 101 + 34 + + + C=0 M=10 Y=95 K=0 + RGB + PROCESS + 255 + 222 + 23 + + + C=85 M=10 Y=100 K=0 + RGB + PROCESS + 0 + 161 + 75 + + + C=100 M=90 Y=0 K=0 + RGB + PROCESS + 33 + 64 + 154 + + + C=60 M=90 Y=0 K=0 + RGB + PROCESS + 127 + 63 + 152 + + + + + + + Adobe PDF library 18.00 + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/src/main/resources/application.properties b/docs/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/docs/src/main/resources/templates/partials/roq-default/head-scripts.html b/docs/src/main/resources/templates/partials/roq-default/head-scripts.html new file mode 100644 index 000000000..50555f4f8 --- /dev/null +++ b/docs/src/main/resources/templates/partials/roq-default/head-scripts.html @@ -0,0 +1,51 @@ +{@java.lang.String tag} + +{#bundle /} + +{#if site.data.containsKey("analytics")} +{#ga4 tag=site.data.getJsonObject('analytics').getString("ga4", "") /} +{/if} + + diff --git a/docs/src/main/resources/templates/partials/roq-default/sidebar-menu.html b/docs/src/main/resources/templates/partials/roq-default/sidebar-menu.html new file mode 100644 index 000000000..0ca55d6de --- /dev/null +++ b/docs/src/main/resources/templates/partials/roq-default/sidebar-menu.html @@ -0,0 +1,16 @@ +{@io.quarkiverse.roq.frontmatter.runtime.model.Site site} +{@java.util.List menu} +{@java.lang.String menuTitle} + + diff --git a/docs/src/main/resources/web/app/main.js b/docs/src/main/resources/web/app/main.js new file mode 100644 index 000000000..756627522 --- /dev/null +++ b/docs/src/main/resources/web/app/main.js @@ -0,0 +1,7 @@ +import hljs from 'highlight.js'; +import CopyButtonPlugin from 'highlightjs-copy'; +import 'highlightjs-copy/dist/highlightjs-copy.min.css'; +import 'highlight.js/styles/github.css'; + +hljs.addPlugin(new CopyButtonPlugin()); +hljs.highlightAll(); diff --git a/docs/web/_custom.css b/docs/web/_custom.css new file mode 100644 index 000000000..f12b4777d --- /dev/null +++ b/docs/web/_custom.css @@ -0,0 +1,103 @@ +/* Theme customization: https://iamroq.dev/theme/default/#css-customization */ +/* Color palette inspired by https://a2a-protocol.org (Material for MkDocs, indigo/white) */ + +@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400&family=Roboto+Mono:wght@400;500&display=swap'); + +@theme inline { + /* Primary accent: Material Design Indigo */ + --color-accent-50: #e8eaf6; + --color-accent-100: #c5cae9; + --color-accent-200: #9fa8da; + --color-accent-300: #7986cb; + --color-accent-400: #5c6bc0; + --color-accent-500: #3f51b5; + --color-accent-600: #3949ab; + --color-accent-700: #303f9f; + --color-accent-800: #283593; + --color-accent-900: #1a237e; + --color-accent-950: #0d1257; + + /* Pop color: same indigo family for buttons, links, and interactive elements */ + --color-pop-50: #e8eaf6; + --color-pop-100: #c5cae9; + --color-pop-200: #9fa8da; + --color-pop-300: #7986cb; + --color-pop-400: #5c6bc0; + --color-pop-500: #3f51b5; + --color-pop-600: #3949ab; + --color-pop-700: #303f9f; + --color-pop-800: #283593; + --color-pop-900: #1a237e; + --color-pop-950: #0d1257; + + /* Typography: Roboto matches Material Design (used by a2a-protocol.org) */ + --font-body: 'Roboto', ui-sans-serif, system-ui, sans-serif; + --font-heading: 'Roboto', ui-sans-serif, system-ui, sans-serif; +} + +/* Sidebar: deep indigo gradient matching a2a-protocol.org dark navigation */ +:root { + --sidebar-bg: linear-gradient(180deg, #303f9f 0%, #1a237e 100%); +} + +/* Hero logo sizing — a2a-java-sdk.png is square (2048x2048) */ +.roq-hero-logo { + @apply w-[200px]; +} + +/* ── Sidebar menu groups ──────────────────────────────────────────────────── */ + +.menu-group-label a { + display: flex !important; + align-items: center !important; + flex-wrap: nowrap !important; + cursor: pointer !important; +} + +.menu-group-chevron { + font-size: 0.65rem; + transition: transform 0.2s ease; + flex-shrink: 0; + margin-left: auto; +} + +.menu-group-children-li { + padding: 0; + margin: 0; + list-style: none; +} + +.menu-group-children-wrapper { + overflow: hidden; + max-height: 300px; + transition: max-height 0.25s ease; + padding: 0; + margin: 0; + list-style: none; +} + +.menu-group-children-wrapper.menu-group-collapsed { + max-height: 0; +} + +.menu-group-child a { + padding-left: 2rem !important; + font-size: 0.9em; + opacity: 0.9; +} + +/* ── Content column width ─────────────────────────────────────────────────── */ + +.page-content .content-main { + max-width: var(--container-5xl); +} + +/* ── Syntax Highlighting (highlight.js) ───────────────────────────────────── */ + +/* Match the site's monospace font (Roboto Mono) */ +.hljs, +pre code.hljs { + font-family: 'Roboto Mono', ui-monospace, monospace; + font-size: 0.875rem; + line-height: 1.6; +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index f684c4d8d..dfd9c670c 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ 1.7.1 4.33.2 0.6.1 - 3.36.1 + 3.36.3 6.0.0 2.0.18 1.5.18