diff --git a/spec/src/main/java/io/a2a/spec/A2AClientError.java b/spec/src/main/java/io/a2a/spec/A2AClientError.java index 2ec8c864e..43b70125a 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientError.java +++ b/spec/src/main/java/io/a2a/spec/A2AClientError.java @@ -1,13 +1,35 @@ package io.a2a.spec; +/** + * Exception class representing errors that occur in A2A client operations. + *

+ * This exception is thrown when client-side errors occur during A2A protocol + * interactions, such as communication failures, invalid responses, or + * protocol violations. + *

+ */ public class A2AClientError extends Exception { + /** + * Constructs a new A2AClientError with no detail message. + */ public A2AClientError() { } + /** + * Constructs a new A2AClientError with the specified detail message. + * + * @param message the detail message explaining the error + */ public A2AClientError(String message) { super(message); } + /** + * Constructs a new A2AClientError with the specified detail message and cause. + * + * @param message the detail message explaining the error + * @param cause the underlying cause of this exception + */ public A2AClientError(String message, Throwable cause) { super(message, cause); } diff --git a/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java b/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java index 95b59a764..7bdb742c2 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java +++ b/spec/src/main/java/io/a2a/spec/A2AClientHTTPError.java @@ -2,10 +2,26 @@ import io.a2a.util.Assert; +/** + * Exception class representing HTTP-specific errors that occur in A2A client operations. + *

+ * This exception extends {@link A2AClientError} and provides additional information + * about HTTP-related failures, including the HTTP status code and error message. + * It is thrown when HTTP communication errors occur during A2A protocol interactions. + *

+ */ public class A2AClientHTTPError extends A2AClientError { private final int code; private final String message; + /** + * Constructs a new A2AClientHTTPError with the specified HTTP status code, message, and data. + * + * @param code the HTTP status code associated with this error + * @param message the error message describing the HTTP error + * @param data additional data associated with the error (currently unused but reserved for future use) + * @throws IllegalArgumentException if message is null + */ public A2AClientHTTPError(int code, String message, Object data) { Assert.checkNotNullParam("code", code); Assert.checkNotNullParam("message", message); diff --git a/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java b/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java index 75988da1c..bdd88bfee 100644 --- a/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java +++ b/spec/src/main/java/io/a2a/spec/A2AClientJSONError.java @@ -1,14 +1,37 @@ package io.a2a.spec; +/** + * Exception class representing JSON-specific errors that occur in A2A client operations. + *

+ * This exception extends {@link A2AClientError} and is thrown when JSON parsing, + * serialization, or deserialization errors occur during A2A protocol interactions. + * Common scenarios include malformed JSON responses, invalid JSON structure, + * or JSON schema validation failures. + *

+ */ public class A2AClientJSONError extends A2AClientError { + /** + * Constructs a new A2AClientJSONError with no detail message. + */ public A2AClientJSONError() { } + /** + * Constructs a new A2AClientJSONError with the specified detail message. + * + * @param message the detail message explaining the JSON error + */ public A2AClientJSONError(String message) { super(message); } + /** + * Constructs a new A2AClientJSONError with the specified detail message and cause. + * + * @param message the detail message explaining the JSON error + * @param cause the underlying cause of this JSON error + */ 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 index 4c9951df2..3817b5132 100644 --- a/spec/src/main/java/io/a2a/spec/A2AError.java +++ b/spec/src/main/java/io/a2a/spec/A2AError.java @@ -1,4 +1,17 @@ package io.a2a.spec; +/** + * Marker interface for all A2A protocol error events. + *

+ * This interface extends {@link Event} and serves as a common type for all + * error-related events in the A2A protocol. It provides a way to categorize + * and handle error events uniformly across the system. + *

+ *

+ * Implementations of this interface represent various types of errors that + * can occur during A2A protocol operations, such as validation errors, + * processing errors, or communication failures. + *

+ */ public interface A2AError extends Event { } diff --git a/spec/src/main/java/io/a2a/spec/A2AServerException.java b/spec/src/main/java/io/a2a/spec/A2AServerException.java index ca2611c2f..fc740c59f 100644 --- a/spec/src/main/java/io/a2a/spec/A2AServerException.java +++ b/spec/src/main/java/io/a2a/spec/A2AServerException.java @@ -5,18 +5,37 @@ */ public class A2AServerException extends A2AException { + /** + * Constructs a new A2AServerException with no detail message. + */ public A2AServerException() { super(); } + /** + * Constructs a new A2AServerException with the specified detail message. + * + * @param msg the detail message explaining the server error + */ public A2AServerException(final String msg) { super(msg); } + /** + * Constructs a new A2AServerException with the specified cause. + * + * @param cause the underlying cause of this server exception + */ public A2AServerException(final Throwable cause) { super(cause); } + /** + * Constructs a new A2AServerException with the specified detail message and cause. + * + * @param msg the detail message explaining the server error + * @param cause the underlying cause of this server exception + */ 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 index acf33feba..eb41d2dc1 100644 --- a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java @@ -55,10 +55,27 @@ public static Location fromString(String location) { } } + /** + * Constructs a new APIKeySecurityScheme with the specified parameters. + * + * @param in the location of the API key (header, query, or cookie) + * @param name the name of the API key parameter + * @param description a description of the security scheme + */ public APIKeySecurityScheme(String in, String name, String description) { this(in, name, description, API_KEY); } + /** + * Constructs a new APIKeySecurityScheme with the specified parameters. + * This constructor is used for JSON deserialization. + * + * @param in the location of the API key (header, query, or cookie) + * @param name the name of the API key parameter + * @param description a description of the security scheme + * @param type the type of security scheme (must be "apiKey") + * @throws IllegalArgumentException if the type is not "apiKey" + */ @JsonCreator public APIKeySecurityScheme(@JsonProperty("in") String in, @JsonProperty("name") String name, @JsonProperty("description") String description, @JsonProperty("type") String type) { @@ -79,38 +96,79 @@ public String getDescription() { } + /** + * Gets the location of the API key. + * + * @return the location where the API key should be placed (header, query, or cookie) + */ public String getIn() { return in; } + /** + * Gets the name of the API key parameter. + * + * @return the parameter name for the API key + */ public String getName() { return name; } + /** + * Gets the type of this security scheme. + * + * @return the security scheme type (always "apiKey") + */ public String getType() { return type; } + /** + * Builder class for constructing APIKeySecurityScheme instances. + */ public static class Builder { private String in; private String name; private String description; + /** + * Sets the location of the API key. + * + * @param in the location where the API key should be placed (header, query, or cookie) + * @return this builder instance for method chaining + */ public Builder in(String in) { this.in = in; return this; } + /** + * Sets the name of the API key parameter. + * + * @param name the parameter name for the API key + * @return this builder instance for method chaining + */ public Builder name(String name) { this.name = name; return this; } + /** + * Sets the description of the security scheme. + * + * @param description a description of the security scheme + * @return this builder instance for method chaining + */ public Builder description(String description) { this.description = description; return this; } + /** + * Builds and returns a new APIKeySecurityScheme instance. + * + * @return a new APIKeySecurityScheme with the configured parameters + */ public APIKeySecurityScheme build() { return new APIKeySecurityScheme(in, name, description); } diff --git a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java index 641f56ccb..8da01b9c8 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCapabilities.java +++ b/spec/src/main/java/io/a2a/spec/AgentCapabilities.java @@ -6,13 +6,22 @@ import com.fasterxml.jackson.annotation.JsonInclude; /** - * An agent's capabilities. + * Represents the optional A2A protocol features and capabilities supported by an agent. + * These capabilities define what advanced features the agent can handle beyond basic messaging. + * + * @param streaming whether the agent supports streaming responses for real-time communication + * @param pushNotifications whether the agent can send push notifications to clients + * @param stateTransitionHistory whether the agent maintains and provides access to state transition history + * @param extensions list of additional extensions or custom capabilities supported by the agent */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record AgentCapabilities(boolean streaming, boolean pushNotifications, boolean stateTransitionHistory, List extensions) { + /** + * Builder class for constructing {@link AgentCapabilities} instances. + */ public static class Builder { private boolean streaming; @@ -20,26 +29,55 @@ public static class Builder { private boolean stateTransitionHistory; private List extensions; + /** + * Sets whether the agent supports streaming responses. + * + * @param streaming {@code true} if the agent supports streaming responses + * @return this builder instance + */ public Builder streaming(boolean streaming) { this.streaming = streaming; return this; } + /** + * Sets whether the agent can send push notifications. + * + * @param pushNotifications {@code true} if the agent supports push notifications + * @return this builder instance + */ public Builder pushNotifications(boolean pushNotifications) { this.pushNotifications = pushNotifications; return this; } + /** + * Sets whether the agent maintains state transition history. + * + * @param stateTransitionHistory {@code true} if the agent provides state transition history + * @return this builder instance + */ public Builder stateTransitionHistory(boolean stateTransitionHistory) { this.stateTransitionHistory = stateTransitionHistory; return this; } + /** + * Sets the list of additional extensions supported by the agent. + * + * @param extensions the list of agent extensions + * @return this builder instance + */ public Builder extensions(List extensions) { this.extensions = extensions; return this; } + /** + * Builds and returns a new {@link AgentCapabilities} instance with the configured properties. + * + * @return a new AgentCapabilities instance + */ public AgentCapabilities build() { return new AgentCapabilities(streaming, pushNotifications, stateTransitionHistory, extensions); } diff --git a/spec/src/main/java/io/a2a/spec/AgentCard.java b/spec/src/main/java/io/a2a/spec/AgentCard.java index e394fb626..805980a47 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCard.java +++ b/spec/src/main/java/io/a2a/spec/AgentCard.java @@ -10,6 +10,43 @@ /** * A public metadata file that describes an agent's capabilities, skills, endpoint URL, and * authentication requirements. Clients use this for discovery. + * + *

An AgentCard conveys key information about an A2A Server: + *

    + *
  • Overall identity and descriptive details
  • + *
  • Service endpoint URL
  • + *
  • Supported A2A protocol capabilities (streaming, push notifications)
  • + *
  • Authentication requirements
  • + *
  • Default input/output content types (MIME types)
  • + *
  • A list of specific skills the agent offers
  • + *
+ * + * @param name Human-readable name of the agent (e.g., "Recipe Advisor Agent") + * @param description A human-readable description of the agent and its general purpose. + * CommonMark MAY be used for rich text formatting. + * @param url The base URL endpoint for the agent's A2A service (where JSON-RPC requests are sent). + * Must be an absolute HTTPS URL for production (e.g., {@code https://agent.example.com/a2a/api}). + * HTTP MAY be used for local development/testing only. + * @param provider Information about the organization or entity providing the agent + * @param version Version string for the agent or its A2A implementation + * (format is defined by the provider, e.g., "1.0.0", "2023-10-26-beta") + * @param documentationUrl URL pointing to human-readable documentation for the agent + * (e.g., API usage, detailed skill descriptions) + * @param capabilities Specifies optional A2A protocol features supported by this agent + * @param defaultInputModes Array of MIME types the agent generally accepts as input across all skills, + * unless overridden by a specific skill + * @param defaultOutputModes Array of MIME types the agent generally produces as output across all skills, + * unless overridden by a specific skill + * @param skills An array of specific skills or capabilities the agent offers. + * Must contain at least one skill if the agent is expected to perform actions beyond simple presence. + * @param supportsAuthenticatedExtendedCard If {@code true}, the agent provides an authenticated endpoint + * ({@code /agent/authenticatedExtendedCard}) relative to the {@code url} field, + * from which a client can retrieve a potentially more detailed Agent Card + * after authenticating. Default: {@code false}. + * @param securitySchemes Security scheme details used for authenticating with this agent. + * {@code null} implies no A2A-advertised auth (not recommended for production) + * @param security Security requirements for contacting the agent + * @param iconUrl URL to an icon representing the agent */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -22,6 +59,11 @@ public record AgentCard(String name, String description, String url, AgentProvid private static final String TEXT_MODE = "text"; + /** + * Compact constructor for AgentCard that validates required parameters. + * This constructor ensures that all essential fields are non-null to maintain + * the integrity of the agent card data. + */ public AgentCard { Assert.checkNotNullParam("capabilities", capabilities); Assert.checkNotNullParam("defaultInputModes", defaultInputModes); @@ -34,6 +76,9 @@ public record AgentCard(String name, String description, String url, AgentProvid Assert.checkNotNullParam("protocolVersion", protocolVersion); } + /** + * Builder class for constructing {@link AgentCard} instances. + */ public static class Builder { private String name; private String description; @@ -53,71 +98,156 @@ public static class Builder { String preferredTransport; String protocolVersion; + /** + * Sets the human-readable name of the agent. + * + * @param name the agent name (e.g., "Recipe Advisor Agent") + * @return this builder instance + */ public Builder name(String name) { this.name = name; return this; } + /** + * Sets the human-readable description of the agent and its general purpose. + * + * @param description the agent description (CommonMark MAY be used for rich text formatting) + * @return this builder instance + */ public Builder description(String description) { this.description = description; return this; } + /** + * Sets the base URL endpoint for the agent's A2A service. + * + * @param url the service endpoint URL (must be absolute HTTPS URL for production) + * @return this builder instance + */ public Builder url(String url) { this.url = url; return this; } + /** + * Sets information about the organization or entity providing the agent. + * + * @param provider the agent provider information + * @return this builder instance + */ public Builder provider(AgentProvider provider) { this.provider = provider; return this; } + /** + * Sets the version string for the agent or its A2A implementation. + * + * @param version the version string (format is defined by the provider) + * @return this builder instance + */ public Builder version(String version) { this.version = version; return this; } + /** + * Sets the URL pointing to human-readable documentation for the agent. + * + * @param documentationUrl the documentation URL + * @return this builder instance + */ public Builder documentationUrl(String documentationUrl) { this.documentationUrl = documentationUrl; return this; } + /** + * Sets the optional A2A protocol features supported by this agent. + * + * @param capabilities the agent capabilities + * @return this builder instance + */ public Builder capabilities(AgentCapabilities capabilities) { this.capabilities = capabilities; return this; } + /** + * Sets the MIME types the agent generally accepts as input across all skills. + * + * @param defaultInputModes the list of input MIME types + * @return this builder instance + */ public Builder defaultInputModes(List defaultInputModes) { this.defaultInputModes = defaultInputModes; return this; } + /** + * Sets the MIME types the agent generally produces as output across all skills. + * + * @param defaultOutputModes the list of output MIME types + * @return this builder instance + */ public Builder defaultOutputModes(List defaultOutputModes) { this.defaultOutputModes = defaultOutputModes; return this; } + /** + * Sets the specific skills or capabilities the agent offers. + * + * @param skills the list of agent skills (must contain at least one skill) + * @return this builder instance + */ public Builder skills(List skills) { this.skills = skills; return this; } + /** + * Sets whether the agent supports providing an extended agent card when authenticated. + * + * @param supportsAuthenticatedExtendedCard {@code true} if the agent provides an authenticated + * extended card endpoint + * @return this builder instance + */ public Builder supportsAuthenticatedExtendedCard(boolean supportsAuthenticatedExtendedCard) { this.supportsAuthenticatedExtendedCard = supportsAuthenticatedExtendedCard; return this; } + /** + * Sets the security scheme details used for authenticating with this agent. + * + * @param securitySchemes the security schemes map + * @return this builder instance + */ public Builder securitySchemes(Map securitySchemes) { this.securitySchemes = securitySchemes; return this; } + /** + * Sets the security requirements for contacting the agent. + * + * @param security the security requirements + * @return this builder instance + */ public Builder security(List>> security) { this.security = security; return this; } + /** + * Sets the URL to an icon representing the agent. + * + * @param iconUrl the icon URL + * @return this builder instance + */ public Builder iconUrl(String iconUrl) { this.iconUrl = iconUrl; return this; @@ -137,7 +267,7 @@ public Builder protocolVersion(String protocolVersion) { this.protocolVersion = protocolVersion; return this; } - + public AgentCard build() { return new AgentCard(name, description, url, provider, version, documentationUrl, capabilities, defaultInputModes, defaultOutputModes, skills, diff --git a/spec/src/main/java/io/a2a/spec/AgentExtension.java b/spec/src/main/java/io/a2a/spec/AgentExtension.java index 931bc1c16..3a874ae13 100644 --- a/spec/src/main/java/io/a2a/spec/AgentExtension.java +++ b/spec/src/main/java/io/a2a/spec/AgentExtension.java @@ -4,38 +4,93 @@ import io.a2a.util.Assert; +/** + * Represents an extension for an A2A agent. + *

+ * Agent extensions provide additional functionality or capabilities that can be + * added to an agent. Each extension is identified by a URI and can include + * parameters, a description, and a required flag indicating whether the + * extension is mandatory for the agent to function properly. + *

+ * + * @param description a human-readable description of the extension + * @param params a map of parameters specific to this extension + * @param required whether this extension is required for the agent to function + * @param uri the unique identifier URI for this extension + */ public record AgentExtension (String description, Map params, boolean required, String uri) { + /** + * Compact constructor that validates the extension parameters. + *

+ * This constructor ensures that the URI parameter is not null, as it is + * required to uniquely identify the extension. + *

+ * + * @throws IllegalArgumentException if uri is null + */ public AgentExtension { Assert.checkNotNullParam("uri", uri); } + /** + * Builder class for constructing AgentExtension instances. + */ public static class Builder { String description; Map params; boolean required; String uri; + /** + * Sets the description of the extension. + * + * @param description a human-readable description of the extension + * @return this builder instance for method chaining + */ public Builder description(String description) { this.description = description; return this; } + /** + * Sets the parameters for the extension. + * + * @param params a map of parameters specific to this extension + * @return this builder instance for method chaining + */ public Builder params(Map params) { this.params = params; return this; } + /** + * Sets whether this extension is required. + * + * @param required true if this extension is required for the agent to function + * @return this builder instance for method chaining + */ public Builder required(boolean required) { this.required = required; return this; } + /** + * Sets the URI identifier for the extension. + * + * @param uri the unique identifier URI for this extension + * @return this builder instance for method chaining + */ public Builder uri(String uri) { this.uri = uri; return this; } + /** + * Builds and returns a new AgentExtension instance. + * + * @return a new AgentExtension with the configured parameters + */ public AgentExtension build() { return new AgentExtension(description, params, required, uri); } diff --git a/spec/src/main/java/io/a2a/spec/AgentProvider.java b/spec/src/main/java/io/a2a/spec/AgentProvider.java index 363d42b03..2f17919f0 100644 --- a/spec/src/main/java/io/a2a/spec/AgentProvider.java +++ b/spec/src/main/java/io/a2a/spec/AgentProvider.java @@ -5,7 +5,11 @@ import io.a2a.util.Assert; /** - * An agent provider. + * Represents information about the organization or entity that provides an agent. + * This includes the organization name and a URL for more information about the provider. + * + * @param organization the name of the organization or entity providing the agent + * @param url a URL pointing to more information about the provider (e.g., company website) */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/spec/src/main/java/io/a2a/spec/AgentSkill.java b/spec/src/main/java/io/a2a/spec/AgentSkill.java index ce9f4811e..d30dd1345 100644 --- a/spec/src/main/java/io/a2a/spec/AgentSkill.java +++ b/spec/src/main/java/io/a2a/spec/AgentSkill.java @@ -7,7 +7,17 @@ import io.a2a.util.Assert; /** - * An agent skill. + * Represents a specific skill or capability that an agent offers. + * Skills define what the agent can do, including the types of input it accepts, + * the output it produces, and examples of how to use the skill. + * + * @param id unique identifier for this skill + * @param name human-readable name of the skill + * @param description detailed description of what this skill does and how to use it + * @param tags list of tags for categorizing and discovering this skill + * @param examples list of example inputs or use cases for this skill + * @param inputModes MIME types this skill accepts as input (overrides agent defaults) + * @param outputModes MIME types this skill produces as output (overrides agent defaults) */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -21,6 +31,9 @@ public record AgentSkill(String id, String name, String description, List inputModes; private List outputModes; + /** + * Sets the unique identifier for this skill. + * + * @param id the skill ID + * @return this builder instance + */ public Builder id(String id) { this.id = id; return this; } + /** + * Sets the human-readable name of the skill. + * + * @param name the skill name + * @return this builder instance + */ public Builder name(String name) { this.name = name; return this; } + /** + * Sets the detailed description of what this skill does. + * + * @param description the skill description + * @return this builder instance + */ public Builder description(String description) { this.description = description; return this; } + /** + * Sets the tags for categorizing and discovering this skill. + * + * @param tags the list of tags + * @return this builder instance + */ public Builder tags(List tags) { this.tags = tags; return this; } + /** + * Sets the example inputs or use cases for this skill. + * + * @param examples the list of examples + * @return this builder instance + */ public Builder examples(List examples) { this.examples = examples; return this; } + /** + * Sets the MIME types this skill accepts as input. + * + * @param inputModes the list of input MIME types + * @return this builder instance + */ public Builder inputModes(List inputModes) { this.inputModes = inputModes; return this; } + /** + * Sets the MIME types this skill produces as output. + * + * @param outputModes the list of output MIME types + * @return this builder instance + */ public Builder outputModes(List outputModes) { this.outputModes = outputModes; return this; } + /** + * Builds and returns a new {@link AgentSkill} instance with the configured properties. + * + * @return a new AgentSkill instance + * @throws IllegalArgumentException if required fields (id, name, description, tags) are null + */ public AgentSkill build() { return new AgentSkill(id, name, description, tags, examples, inputModes, outputModes); } diff --git a/spec/src/main/java/io/a2a/spec/Artifact.java b/spec/src/main/java/io/a2a/spec/Artifact.java index 5a5baa063..8153fcf0b 100644 --- a/spec/src/main/java/io/a2a/spec/Artifact.java +++ b/spec/src/main/java/io/a2a/spec/Artifact.java @@ -8,13 +8,30 @@ import io.a2a.util.Assert; /** - * Represents outputs generated by an agent during a task (e.g., generated files or final structured - * data). Contains parts. + * Represents outputs generated by an agent during a task execution. + * Artifacts are the deliverables or results produced by agents, such as generated files, + * processed data, or any other structured output. Each artifact contains one or more + * content parts and associated metadata. + * + * @param artifactId unique identifier for this artifact + * @param name human-readable name for this artifact + * @param description optional description explaining what this artifact contains + * @param parts the content parts that make up this artifact (must not be empty) + * @param metadata additional metadata associated with this artifact */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record Artifact(String artifactId, String name, String description, List> parts, Map metadata) { + /** + * Compact constructor that validates the artifact parameters. + *

+ * This constructor ensures that the artifact ID and parts are not null, + * and that the parts list is not empty, as artifacts must contain content. + *

+ * + * @throws IllegalArgumentException if artifactId is null, parts is null, or parts is empty + */ public Artifact { Assert.checkNotNullParam("artifactId", artifactId); Assert.checkNotNullParam("parts", parts); @@ -23,6 +40,9 @@ public record Artifact(String artifactId, String name, String description, List< } } + /** + * Builder class for constructing {@link Artifact} instances. + */ public static class Builder { private String artifactId; private String name; @@ -30,9 +50,17 @@ public static class Builder { private List> parts; private Map metadata; + /** + * Creates a new empty Builder. + */ public Builder(){ } + /** + * Creates a new Builder initialized with values from an existing Artifact. + * + * @param existingArtifact the artifact to copy values from + */ public Builder(Artifact existingArtifact) { artifactId = existingArtifact.artifactId; name = existingArtifact.name; @@ -41,37 +69,78 @@ public Builder(Artifact existingArtifact) { metadata = existingArtifact.metadata; } + /** + * Sets the unique identifier for this artifact. + * + * @param artifactId the artifact ID + * @return this builder instance + */ public Builder artifactId(String artifactId) { this.artifactId = artifactId; return this; } - + /** + * Sets the human-readable name for this artifact. + * + * @param name the artifact name + * @return this builder instance + */ public Builder name(String name) { this.name = name; return this; } + /** + * Sets the description explaining what this artifact contains. + * + * @param description the artifact description + * @return this builder instance + */ public Builder description(String description) { this.description = description; return this; } + /** + * Sets the content parts that make up this artifact. + * + * @param parts the list of content parts (must not be empty) + * @return this builder instance + */ public Builder parts(List> parts) { this.parts = parts; return this; } + /** + * Sets the content parts that make up this artifact using varargs. + * + * @param parts the content parts as varargs (must not be empty) + * @return this builder instance + */ public Builder parts(Part... parts) { this.parts = List.of(parts); return this; } + /** + * Sets the additional metadata associated with this artifact. + * + * @param metadata the metadata map + * @return this builder instance + */ public Builder metadata(Map metadata) { this.metadata = metadata; return this; } + /** + * Builds and returns a new {@link Artifact} instance with the configured properties. + * + * @return a new Artifact instance + * @throws IllegalArgumentException if artifactId is null, parts is null, or parts is empty + */ public Artifact build() { return new Artifact(artifactId, name, description, parts, metadata); } diff --git a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java b/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java index d28a1e173..328b51bcd 100644 --- a/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java +++ b/spec/src/main/java/io/a2a/spec/AuthenticationInfo.java @@ -7,12 +7,29 @@ import io.a2a.util.Assert; /** - * The authentication info for an agent. + * Represents authentication information for an A2A agent. + *

+ * This record contains the authentication schemes supported by the agent + * and any associated credentials. The authentication information is used + * to establish secure communication between agents in the A2A protocol. + *

+ * + * @param schemes a list of supported authentication scheme names + * @param credentials the authentication credentials (optional) */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record AuthenticationInfo(List schemes, String credentials) { + /** + * Compact constructor that validates the authentication information. + *

+ * This constructor ensures that the schemes list is not null, as at least + * one authentication scheme must be specified. + *

+ * + * @throws IllegalArgumentException if schemes is null + */ public AuthenticationInfo { Assert.checkNotNullParam("schemes", schemes); } diff --git a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java b/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java index 0723a1281..404badea8 100644 --- a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java @@ -9,12 +9,20 @@ /** * Configuration for the OAuth Authorization Code flow. + * This flow is used for server-side applications where the client can securely store credentials. + * The authorization code flow involves redirecting the user to the authorization server, + * obtaining an authorization code, and then exchanging it for an access token. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record AuthorizationCodeOAuthFlow(String authorizationUrl, String refreshUrl, Map scopes, String tokenUrl) { + /** + * Compact constructor that validates the required parameters. + * + * @throws IllegalArgumentException if any required parameter is null + */ public AuthorizationCodeOAuthFlow { Assert.checkNotNullParam("authorizationUrl", authorizationUrl); Assert.checkNotNullParam("scopes", scopes); diff --git a/spec/src/main/java/io/a2a/spec/CancelTaskRequest.java b/spec/src/main/java/io/a2a/spec/CancelTaskRequest.java index 39c370ae3..ace875b5d 100644 --- a/spec/src/main/java/io/a2a/spec/CancelTaskRequest.java +++ b/spec/src/main/java/io/a2a/spec/CancelTaskRequest.java @@ -12,14 +12,27 @@ import io.a2a.util.Assert; /** - * A request that can be used to cancel a task. + * A JSON-RPC request that can be used to cancel a running or pending task. + * This request follows the A2A protocol specification for task cancellation. + * When a task is successfully cancelled, it transitions to the "canceled" state. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class CancelTaskRequest extends NonStreamingJSONRPCRequest { + /** The JSON-RPC method name for canceling tasks. */ public static final String METHOD = "tasks/cancel"; + /** + * Creates a new CancelTaskRequest with full parameter specification. + * This constructor is primarily used by Jackson for JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the request identifier (string, number, or null) + * @param method the method name (must be "tasks/cancel") + * @param params the task parameters containing the task ID to cancel + * @throws IllegalArgumentException if the JSON-RPC version is invalid, method is incorrect, or required parameters are null + */ @JsonCreator public CancelTaskRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("method") String method, @JsonProperty("params") TaskIdParams params) { @@ -38,36 +51,77 @@ public CancelTaskRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty( this.params = params; } + /** + * Creates a new CancelTaskRequest with simplified parameters. + * The JSON-RPC version defaults to "2.0" and the method is automatically set to "tasks/cancel". + * + * @param id the request identifier (string, number, or null) + * @param params the task parameters containing the task ID to cancel + */ public CancelTaskRequest(Object id, TaskIdParams params) { this(null, id, METHOD, params); } + /** + * Builder class for constructing CancelTaskRequest instances. + * Provides a fluent API for setting request parameters with sensible defaults. + */ public static class Builder { private String jsonrpc; private Object id; private String method = METHOD; private TaskIdParams params; + /** + * Sets the JSON-RPC protocol version. + * + * @param jsonrpc the JSON-RPC version (typically "2.0") + * @return this builder instance for method chaining + */ public CancelTaskRequest.Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } + /** + * Sets the request identifier. + * + * @param id the request identifier (string, number, or null) + * @return this builder instance for method chaining + */ public CancelTaskRequest.Builder id(Object id) { this.id = id; return this; } + /** + * Sets the JSON-RPC method name. + * + * @param method the method name (should be "tasks/cancel") + * @return this builder instance for method chaining + */ public CancelTaskRequest.Builder method(String method) { this.method = method; return this; } + /** + * Sets the task parameters containing the task ID to cancel. + * + * @param params the task parameters + * @return this builder instance for method chaining + */ public CancelTaskRequest.Builder params(TaskIdParams params) { this.params = params; return this; } + /** + * Builds the CancelTaskRequest instance. + * If no ID is specified, a random UUID will be generated. + * + * @return a new CancelTaskRequest instance + */ public CancelTaskRequest build() { if (id == null) { id = UUID.randomUUID().toString(); diff --git a/spec/src/main/java/io/a2a/spec/CancelTaskResponse.java b/spec/src/main/java/io/a2a/spec/CancelTaskResponse.java index 9ef775118..ab3f3282d 100644 --- a/spec/src/main/java/io/a2a/spec/CancelTaskResponse.java +++ b/spec/src/main/java/io/a2a/spec/CancelTaskResponse.java @@ -6,23 +6,47 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * A response to a cancel task request. + * A JSON-RPC response to a cancel task request. + * This response contains either the cancelled task information or an error if the cancellation failed. + * A successful response will include the task with its state updated to "canceled". */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class CancelTaskResponse extends JSONRPCResponse { + /** + * Creates a new CancelTaskResponse with full parameter specification. + * This constructor is primarily used by Jackson for JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (typically "2.0") + * @param id the request identifier that matches the original request + * @param result the cancelled task object (null if there was an error) + * @param error the error information (null if the operation was successful) + */ @JsonCreator public CancelTaskResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("result") Task result, @JsonProperty("error") JSONRPCError error) { super(jsonrpc, id, result, error, Task.class); } + /** + * Creates a new CancelTaskResponse for an error case. + * The JSON-RPC version defaults to "2.0" and the result is set to null. + * + * @param id the request identifier that matches the original request + * @param error the error information describing why the cancellation failed + */ public CancelTaskResponse(Object id, JSONRPCError error) { this(null, id, null, error); } - + /** + * Creates a new CancelTaskResponse for a successful case. + * The JSON-RPC version defaults to "2.0" and the error is set to null. + * + * @param id the request identifier that matches the original request + * @param result the cancelled task object with updated state + */ public CancelTaskResponse(Object id, Task result) { this(null, id, result, null); } diff --git a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java b/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java index 05322cc0b..b9922077c 100644 --- a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java @@ -10,11 +10,19 @@ /** * Configuration for the OAuth Client Credentials flow. + * This flow is used for server-to-server authentication where the client application + * authenticates directly with the authorization server using its own credentials. + * No user interaction is required for this flow. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record ClientCredentialsOAuthFlow(String refreshUrl, Map scopes, String tokenUrl) { + /** + * Compact constructor that validates the required parameters. + * + * @throws IllegalArgumentException if any required parameter 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 index d05ee3202..45fdd88eb 100644 --- a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java @@ -7,12 +7,26 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * A JSON-RPC error indicating that the requested content type is not supported by the agent. + * This error is returned when a client requests input or output in a MIME type that the agent + * cannot handle or process. The error code follows the JSON-RPC 2.0 specification for + * application-specific errors. + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class ContentTypeNotSupportedError extends JSONRPCError { + /** The default error code for content type not supported errors (-32005). */ public final static Integer DEFAULT_CODE = -32005; + /** + * Creates a new ContentTypeNotSupportedError with the specified parameters. + * + * @param code the error code (defaults to -32005 if null) + * @param message the error message (defaults to "Incompatible content types" if null) + * @param data additional error data (optional) + */ @JsonCreator public ContentTypeNotSupportedError( @JsonProperty("code") Integer code, diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/io/a2a/spec/DataPart.java index 1449f55ac..0689d6545 100644 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ b/spec/src/main/java/io/a2a/spec/DataPart.java @@ -9,7 +9,13 @@ import io.a2a.util.Assert; /** - * A fundamental data unit within a Message or Artifact. + * Represents a data part within a Message or Artifact in the A2A protocol. + *

+ * A DataPart contains structured data in the form of a map of key-value pairs. + * This type of part is used to transmit arbitrary structured data between + * agents, such as JSON objects, configuration data, or any other structured + * information that can be represented as a map. + *

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -19,10 +25,23 @@ public class DataPart extends Part> { private final Map metadata; private final Kind kind; + /** + * Constructs a new DataPart with the specified data and no metadata. + * + * @param data the structured data to be contained in this part + */ public DataPart(Map data) { this(data, null); } + /** + * Constructs a new DataPart with the specified data and metadata. + * This constructor is used for JSON deserialization. + * + * @param data the structured data to be contained in this part + * @param metadata optional metadata associated with this data part + * @throws IllegalArgumentException if data is null + */ @JsonCreator public DataPart(@JsonProperty("data") Map data, @JsonProperty("metadata") Map metadata) { @@ -37,6 +56,11 @@ public Kind getKind() { return kind; } + /** + * Gets the structured data contained in this part. + * + * @return the map containing the structured data + */ public Map getData() { return data; } diff --git a/spec/src/main/java/io/a2a/spec/Event.java b/spec/src/main/java/io/a2a/spec/Event.java index 4d0daa531..dc5b9cb93 100644 --- a/spec/src/main/java/io/a2a/spec/Event.java +++ b/spec/src/main/java/io/a2a/spec/Event.java @@ -1,4 +1,15 @@ package io.a2a.spec; +/** + * Marker interface for events in the A2A protocol. + * + * This interface serves as a base type for all event objects that can be + * transmitted or processed within the A2A (Agent-to-Agent) communication framework. + * Events represent various types of notifications, state changes, or data updates + * that occur during agent interactions. + * + * Implementing classes should define specific event types such as task updates, + * message events, or system notifications. + */ 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 index 07ab3fe9f..c3452c0ea 100644 --- a/spec/src/main/java/io/a2a/spec/EventKind.java +++ b/spec/src/main/java/io/a2a/spec/EventKind.java @@ -6,6 +6,22 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +/** + * Interface for objects that can be categorized by a specific "kind" in the A2A protocol. + * + * This interface provides polymorphic JSON serialization/deserialization support + * for different types of events and objects in the A2A framework. The "kind" property + * is used as a discriminator to determine the concrete type during JSON processing. + * + * Currently supported kinds include: + *
    + *
  • {@code "task"} - Represents a {@link Task} object
  • + *
  • {@code "message"} - Represents a {@link Message} object
  • + *
+ * + * The Jackson annotations configure automatic type resolution based on the "kind" field + * in JSON data, enabling seamless conversion between JSON and the appropriate Java types. + */ @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, @@ -18,5 +34,14 @@ }) public interface EventKind { + /** + * Returns the kind/type identifier for this object. + * + * This method provides the discriminator value used for JSON serialization + * and type resolution. The returned string should match one of the values + * defined in the {@link JsonSubTypes} annotation. + * + * @return the kind identifier (e.g., "task", "message") + */ String getKind(); } diff --git a/spec/src/main/java/io/a2a/spec/FileContent.java b/spec/src/main/java/io/a2a/spec/FileContent.java index f9609fb8b..bcb97d243 100644 --- a/spec/src/main/java/io/a2a/spec/FileContent.java +++ b/spec/src/main/java/io/a2a/spec/FileContent.java @@ -2,10 +2,35 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +/** + * Sealed interface representing file content in the A2A protocol. + *

+ * This interface defines the contract for file content that can be transmitted + * between agents. File content can be represented in two ways: + *

+ *
    + *
  • {@link FileWithBytes} - File content with embedded byte data
  • + *
  • {@link FileWithUri} - File content referenced by a URI
  • + *
+ *

+ * The interface uses a custom deserializer to handle the polymorphic nature + * of file content during JSON deserialization. + *

+ */ @JsonDeserialize(using = FileContentDeserializer.class) public sealed interface FileContent permits FileWithBytes, FileWithUri { + /** + * Gets the MIME type of the file content. + * + * @return the MIME type string (e.g., "text/plain", "image/jpeg") + */ String mimeType(); + /** + * Gets the name of the file. + * + * @return the file name including extension + */ String name(); } diff --git a/spec/src/main/java/io/a2a/spec/FileContentDeserializer.java b/spec/src/main/java/io/a2a/spec/FileContentDeserializer.java index aa763db42..9c55a5952 100644 --- a/spec/src/main/java/io/a2a/spec/FileContentDeserializer.java +++ b/spec/src/main/java/io/a2a/spec/FileContentDeserializer.java @@ -8,16 +8,41 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +/** + * Custom Jackson deserializer for FileContent objects. + * This deserializer handles the polymorphic nature of file content, which can be represented + * either as base64-encoded bytes or as a URI reference. It determines the appropriate + * FileContent subtype based on the presence of "bytes" or "uri" fields in the JSON. + */ public class FileContentDeserializer extends StdDeserializer { + /** + * Default constructor for the deserializer. + */ public FileContentDeserializer() { this(null); } + /** + * Constructor with value class specification. + * + * @param vc the value class being deserialized + */ public FileContentDeserializer(Class vc) { super(vc); } + /** + * Deserializes JSON into a FileContent object. + * The method examines the JSON structure to determine whether to create + * a FileWithBytes or FileWithUri instance based on the available fields. + * + * @param jsonParser the JSON parser + * @param context the deserialization context + * @return a FileContent instance (either FileWithBytes or FileWithUri) + * @throws IOException if there's an I/O error during parsing + * @throws JsonProcessingException if the JSON structure is invalid + */ @Override public FileContent deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { @@ -25,13 +50,19 @@ public FileContent deserialize(JsonParser jsonParser, DeserializationContext con JsonNode mimeType = node.get("mimeType"); JsonNode name = node.get("name"); JsonNode bytes = node.get("bytes"); + + // Check if the file content is provided as base64-encoded bytes if (bytes != null) { return new FileWithBytes(mimeType != null ? mimeType.asText() : null, name != null ? name.asText() : null, bytes.asText()); - } else if (node.has("uri")) { + } + // Check if the file content is provided as a URI reference + else if (node.has("uri")) { return new FileWithUri(mimeType != null ? mimeType.asText() : null, name != null ? name.asText() : null, node.get("uri").asText()); - } else { + } + // Neither bytes nor uri field is present - invalid format + else { throw new IOException("Invalid file format: missing 'bytes' or 'uri'"); } } diff --git a/spec/src/main/java/io/a2a/spec/FilePart.java b/spec/src/main/java/io/a2a/spec/FilePart.java index f4c1d0f8e..9b876d388 100644 --- a/spec/src/main/java/io/a2a/spec/FilePart.java +++ b/spec/src/main/java/io/a2a/spec/FilePart.java @@ -9,7 +9,13 @@ import io.a2a.util.Assert; /** - * A fundamental file unit within a Message or Artifact. + * Represents a file part within a Message or Artifact in the A2A protocol. + *

+ * A FilePart contains file content that can be transmitted between agents. + * The file content can be either embedded as bytes ({@link FileWithBytes}) + * or referenced by a URI ({@link FileWithUri}). This part type is used + * for sharing documents, images, or any other file-based content. + *

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -19,10 +25,23 @@ public class FilePart extends Part { private final Map metadata; private final Kind kind; + /** + * Constructs a new FilePart with the specified file content and no metadata. + * + * @param file the file content to be contained in this part + */ public FilePart(FileContent file) { this(file, null); } + /** + * Constructs a new FilePart with the specified file content and metadata. + * This constructor is used for JSON deserialization. + * + * @param file the file content to be contained in this part + * @param metadata optional metadata associated with this file part + * @throws IllegalArgumentException if file is null + */ @JsonCreator public FilePart(@JsonProperty("file") FileContent file, @JsonProperty("metadata") Map metadata) { Assert.checkNotNullParam("file", file); @@ -36,6 +55,11 @@ public Kind getKind() { return kind; } + /** + * Gets the file content contained in this part. + * + * @return the file content + */ public FileContent getFile() { return file; } diff --git a/spec/src/main/java/io/a2a/spec/FileWithBytes.java b/spec/src/main/java/io/a2a/spec/FileWithBytes.java index e2259e902..60eaff87a 100644 --- a/spec/src/main/java/io/a2a/spec/FileWithBytes.java +++ b/spec/src/main/java/io/a2a/spec/FileWithBytes.java @@ -3,6 +3,22 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; +/** + * Represents file content with embedded byte data in the A2A protocol. + *

+ * This implementation of {@link FileContent} contains the actual file data + * as a base64-encoded string. This approach is suitable for smaller files + * that can be efficiently transmitted as part of the message payload. + *

+ *

+ * For larger files or when bandwidth is a concern, consider using + * {@link FileWithUri} instead, which references the file by URI. + *

+ * + * @param mimeType the MIME type of the file (e.g., "text/plain", "image/jpeg") + * @param name the name of the file including extension + * @param bytes the file content encoded as a base64 string + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) 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 index 65db42dc5..06ba411c1 100644 --- a/spec/src/main/java/io/a2a/spec/FileWithUri.java +++ b/spec/src/main/java/io/a2a/spec/FileWithUri.java @@ -3,6 +3,24 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; +/** + * Represents file content referenced by a URI in the A2A protocol. + *

+ * This implementation of {@link FileContent} contains a reference to file data + * via a URI instead of embedding the actual file content. This approach is + * more efficient for larger files or when bandwidth optimization is important, + * as it avoids including the file data directly in the message payload. + *

+ *

+ * The URI can point to various locations such as HTTP/HTTPS URLs, file system + * paths, or other accessible resource identifiers. The receiving agent is + * responsible for retrieving the file content from the specified URI. + *

+ * + * @param mimeType the MIME type of the file (e.g., "text/plain", "image/jpeg") + * @param name the name of the file including extension + * @param uri the URI where the file content can be accessed + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record FileWithUri(String mimeType, String name, String uri) implements FileContent { diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigRequest.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigRequest.java index b353e0cc8..e87c3a72e 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigRequest.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigRequest.java @@ -10,14 +10,28 @@ import java.util.UUID; /** - * A get task push notification request. + * A JSON-RPC request to retrieve the push notification configuration for a specific task. + * This request is used to get the current webhook configuration that the server uses + * to send asynchronous task updates to the client. Push notifications are useful for + * long-running tasks where the client may not maintain a persistent connection. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class GetTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { + /** The JSON-RPC method name for getting push notification configuration. */ public static final String METHOD = "tasks/pushNotificationConfig/get"; + /** + * Creates a new GetTaskPushNotificationConfigRequest with full parameter specification. + * This constructor is primarily used by Jackson for JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the request identifier (string, number, or null) + * @param method the method name (must be "tasks/pushNotificationConfig/get") + * @param params the task parameters containing the task ID + * @throws IllegalArgumentException if the JSON-RPC version is invalid, method is incorrect, or required parameters are null + */ @JsonCreator public GetTaskPushNotificationConfigRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("method") String method, @JsonProperty("params") GetTaskPushNotificationConfigParams params) { diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigResponse.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigResponse.java index 116799a9e..e02223907 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigResponse.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigResponse.java @@ -6,12 +6,24 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * A response for a get task push notification request. + * A JSON-RPC response containing the push notification configuration for a task. + * This response provides the webhook configuration details that the server uses + * to send asynchronous task updates to the client. The configuration includes + * the webhook URL, HTTP method, headers, and other notification settings. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class GetTaskPushNotificationConfigResponse extends JSONRPCResponse { + /** + * Creates a new GetTaskPushNotificationConfigResponse with full parameter specification. + * This constructor is primarily used by Jackson for JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the response identifier matching the original request + * @param result the push notification configuration if the request was successful + * @param error the error information if the request failed + */ @JsonCreator public GetTaskPushNotificationConfigResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("result") TaskPushNotificationConfig result, @@ -19,10 +31,24 @@ public GetTaskPushNotificationConfigResponse(@JsonProperty("jsonrpc") String jso super(jsonrpc, id, result, error, TaskPushNotificationConfig.class); } + /** + * Creates an error GetTaskPushNotificationConfigResponse with error information. + * The JSON-RPC version defaults to "2.0" and no result is set. + * + * @param id the response identifier matching the original request + * @param error the error information explaining why the request failed + */ public GetTaskPushNotificationConfigResponse(Object id, JSONRPCError error) { this(null, id, null, error); } + /** + * Creates a successful GetTaskPushNotificationConfigResponse with the push notification configuration. + * The JSON-RPC version defaults to "2.0" and no error is set. + * + * @param id the response identifier matching the original request + * @param result the push notification configuration + */ public GetTaskPushNotificationConfigResponse(Object id, TaskPushNotificationConfig result) { this(null, id, result, null); } diff --git a/spec/src/main/java/io/a2a/spec/GetTaskRequest.java b/spec/src/main/java/io/a2a/spec/GetTaskRequest.java index f31237af0..267d75abc 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskRequest.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskRequest.java @@ -12,14 +12,28 @@ import io.a2a.util.Assert; /** - * A get task request. + * A JSON-RPC request to retrieve information about a specific task. + * This request is used to get the current status, progress, and details of a task + * that was previously created. It allows clients to check on the state of + * long-running operations and retrieve their results when completed. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class GetTaskRequest extends NonStreamingJSONRPCRequest { + /** The JSON-RPC method name for getting task information. */ public static final String METHOD = "tasks/get"; + /** + * Creates a new GetTaskRequest with full parameter specification. + * This constructor is primarily used by Jackson for JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the request identifier (string, number, or null) + * @param method the method name (must be "tasks/get") + * @param params the task parameters containing the task query information + * @throws IllegalArgumentException if the JSON-RPC version is invalid, method is incorrect, or required parameters are null + */ @JsonCreator public GetTaskRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("method") String method, @JsonProperty("params") TaskQueryParams params) { @@ -38,37 +52,79 @@ public GetTaskRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id this.params = params; } + /** + * Creates a new GetTaskRequest with simplified parameters. + * The JSON-RPC version defaults to "2.0" and the method is automatically set. + * + * @param id the request identifier (string, number, or null) + * @param params the task parameters containing the task query information + */ public GetTaskRequest(Object id, TaskQueryParams params) { this(null, id, METHOD, params); } + /** + * Builder class for constructing GetTaskRequest instances. + * Provides a fluent interface for setting request parameters and automatically + * generates a unique request ID if none is provided. + */ public static class Builder { private String jsonrpc; private Object id; private String method = "tasks/get"; private TaskQueryParams params; + /** + * Sets the JSON-RPC protocol version. + * + * @param jsonrpc the JSON-RPC version (typically "2.0") + * @return this builder instance for method chaining + */ public GetTaskRequest.Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } + /** + * Sets the request identifier. + * + * @param id the request ID (string, number, or null) + * @return this builder instance for method chaining + */ public GetTaskRequest.Builder id(Object id) { this.id = id; return this; } + /** + * Sets the JSON-RPC method name. + * + * @param method the method name (should be "tasks/get") + * @return this builder instance for method chaining + */ public GetTaskRequest.Builder method(String method) { this.method = method; return this; } + /** + * Sets the task query parameters. + * + * @param params the parameters containing task query information + * @return this builder instance for method chaining + */ public GetTaskRequest.Builder params(TaskQueryParams params) { this.params = params; return this; } + /** + * Builds and returns a new GetTaskRequest instance. + * If no request ID was set, a random UUID will be generated. + * + * @return a new GetTaskRequest with the configured parameters + */ public GetTaskRequest build() { if (id == null) { id = UUID.randomUUID().toString(); diff --git a/spec/src/main/java/io/a2a/spec/GetTaskResponse.java b/spec/src/main/java/io/a2a/spec/GetTaskResponse.java index 0d27a8e68..612f99df9 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskResponse.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskResponse.java @@ -6,23 +6,50 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * The response for a get task request. + * A JSON-RPC response containing task information. + * This response provides detailed information about a task including its current status, + * progress, metadata, and results (if completed). It is returned in response to a + * GetTaskRequest and allows clients to monitor the state of long-running operations. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class GetTaskResponse extends JSONRPCResponse { + /** + * Creates a new GetTaskResponse with full parameter specification. + * This constructor is primarily used by Jackson for JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the response identifier matching the original request + * @param result the task information if the request was successful + * @param error the error information if the request failed + */ @JsonCreator public GetTaskResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("result") Task result, @JsonProperty("error") JSONRPCError error) { super(jsonrpc, id, result, error, Task.class); } - public GetTaskResponse(Object id, JSONRPCError error) { - this(null, id, null, error); - } - + /** + * Creates a successful GetTaskResponse with task information. + * The JSON-RPC version defaults to "2.0" and no error is set. + * + * @param id the response identifier matching the original request + * @param result the task information including status, progress, and results + */ public GetTaskResponse(Object id, Task result) { this(null, id, result, null); } + + /** + * Creates an error GetTaskResponse with error information. + * The JSON-RPC version defaults to "2.0" and no result is set. + * + * @param id the response identifier matching the original request + * @param error the error information explaining why the request failed + */ + public GetTaskResponse(Object id, JSONRPCError error) { + this(null, id, null, error); + } + } diff --git a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java b/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java index 029419a19..79ca468be 100644 --- a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java @@ -8,22 +8,55 @@ import io.a2a.util.Assert; /** - * Represents an HTTP authentication security scheme. + * Represents an HTTP authentication security scheme as defined in the A2A specification. + * This corresponds to the HTTPAuthSecurityScheme interface in the TypeScript definitions. + * + * HTTP Authentication security schemes define how clients should authenticate using + * standard HTTP authentication methods as specified in RFC7235. The scheme name + * should be registered in the IANA Authentication Scheme registry. + * + * @see RFC7235 - HTTP Authentication */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class HTTPAuthSecurityScheme implements SecurityScheme { + /** The type identifier for HTTP authentication schemes */ public static final String HTTP = "http"; + + /** A hint to identify how the bearer token is formatted (optional) */ private final String bearerFormat; + + /** The name of the HTTP Authentication scheme (e.g., "Basic", "Bearer") */ private final String scheme; + + /** Description of this security scheme (optional) */ private final String description; + + /** The type of security scheme, must be "http" */ private final String type; + /** + * Convenience constructor that defaults the type to "http". + * + * @param bearerFormat A hint to identify how the bearer token is formatted (optional) + * @param scheme The name of the HTTP Authentication scheme (required) + * @param description Description of this security scheme (optional) + */ public HTTPAuthSecurityScheme(String bearerFormat, String scheme, String description) { this(bearerFormat, scheme, description, HTTP); } + /** + * Full constructor for HTTP authentication security scheme. + * Used by Jackson for JSON deserialization. + * + * @param bearerFormat A hint to identify how the bearer token is formatted (optional) + * @param scheme The name of the HTTP Authentication scheme (required, case-insensitive) + * @param description Description of this security scheme (optional) + * @param type The type of security scheme, must be "http" + * @throws IllegalArgumentException if type is not "http" + */ @JsonCreator public HTTPAuthSecurityScheme(@JsonProperty("bearerFormat") String bearerFormat, @JsonProperty("scheme") String scheme, @JsonProperty("description") String description, @JsonProperty("type") String type) { @@ -37,43 +70,96 @@ public HTTPAuthSecurityScheme(@JsonProperty("bearerFormat") String bearerFormat, this.type = type; } + /** + * Returns the description of this security scheme. + * + * @return the description, or null if not specified + */ @Override public String getDescription() { return description; } + /** + * Returns the bearer format hint for this security scheme. + * This is primarily for documentation purposes to help identify + * how bearer tokens are formatted. + * + * @return the bearer format hint, or null if not specified + */ public String getBearerFormat() { return bearerFormat; } + /** + * Returns the HTTP authentication scheme name. + * This should be a registered scheme in the IANA Authentication Scheme registry. + * Common values include "Basic", "Bearer", "Digest", etc. + * + * @return the scheme name (case-insensitive) + */ public String getScheme() { return scheme; } + /** + * Returns the type of this security scheme. + * For HTTPAuthSecurityScheme, this is always "http". + * + * @return "http" + */ public String getType() { return type; } + /** + * Builder class for constructing HTTPAuthSecurityScheme instances. + * Provides a fluent API for setting optional parameters. + */ public static class Builder { private String bearerFormat; private String scheme; private String description; + /** + * Sets the bearer format hint. + * + * @param bearerFormat A hint to identify how bearer tokens are formatted + * @return this builder instance for method chaining + */ public Builder bearerFormat(String bearerFormat) { this.bearerFormat = bearerFormat; return this; } + /** + * Sets the HTTP authentication scheme name. + * + * @param scheme The name of the HTTP Authentication scheme (required) + * @return this builder instance for method chaining + */ public Builder scheme(String scheme) { this.scheme = scheme; return this; } + /** + * Sets the description of this security scheme. + * + * @param description Description of this security scheme + * @return this builder instance for method chaining + */ public Builder description(String description) { this.description = description; return this; } + /** + * Builds the HTTPAuthSecurityScheme instance. + * + * @return a new HTTPAuthSecurityScheme instance + * @throws IllegalArgumentException if required parameters are missing + */ public HTTPAuthSecurityScheme build() { return new HTTPAuthSecurityScheme(bearerFormat, scheme, description); } diff --git a/spec/src/main/java/io/a2a/spec/IdJsonMappingException.java b/spec/src/main/java/io/a2a/spec/IdJsonMappingException.java index 15e0b07b1..64e87f326 100644 --- a/spec/src/main/java/io/a2a/spec/IdJsonMappingException.java +++ b/spec/src/main/java/io/a2a/spec/IdJsonMappingException.java @@ -2,20 +2,49 @@ import com.fasterxml.jackson.databind.JsonMappingException; +/** + * A specialized JsonMappingException that carries a JSON-RPC request ID. + * This exception is used when JSON mapping errors occur during processing + * of JSON-RPC requests, allowing the error response to include the original + * request ID for proper correlation. + * + * According to JSON-RPC 2.0 specification, error responses should include + * the same ID as the request that caused the error, or null if the ID + * could not be determined. + */ public class IdJsonMappingException extends JsonMappingException { + /** The JSON-RPC request ID associated with this mapping error */ Object id; + /** + * Constructs a new IdJsonMappingException with the specified message and request ID. + * + * @param msg the detail message explaining the mapping error + * @param id the JSON-RPC request ID (can be String, Number, or null) + */ public IdJsonMappingException(String msg, Object id) { super(null, msg); this.id = id; } + /** + * Constructs a new IdJsonMappingException with the specified message, cause, and request ID. + * + * @param msg the detail message explaining the mapping error + * @param cause the underlying cause of the mapping error + * @param id the JSON-RPC request ID (can be String, Number, or null) + */ public IdJsonMappingException(String msg, Throwable cause, Object id) { super(null, msg, cause); this.id = id; } + /** + * Returns the JSON-RPC request ID associated with this mapping error. + * + * @return the request ID, or null if not available + */ public Object getId() { return id; } diff --git a/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java b/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java index 46e76cc84..76a635675 100644 --- a/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java @@ -8,12 +8,28 @@ import io.a2a.util.Assert; /** - * Configuration for the OAuth Implicit flow. + * Configuration for the OAuth 2.0 Implicit flow as defined in the A2A specification. + * This corresponds to the ImplicitOAuthFlow interface in the TypeScript definitions. + * + * The Implicit flow is used for client-side applications that cannot securely store + * client credentials. The authorization server issues access tokens directly to the + * client without requiring client authentication. + * + * @param authorizationUrl The authorization URL to be used for this flow (required, must be HTTPS) + * @param refreshUrl The URL to be used for obtaining refresh tokens (optional, must be HTTPS if provided) + * @param scopes The available scopes for the OAuth2 security scheme (required, may be empty) + * + * @see RFC 6749 Section 4.2 - Implicit Grant */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record ImplicitOAuthFlow(String authorizationUrl, String refreshUrl, Map scopes) { + /** + * Compact constructor that validates required parameters. + * + * @throws IllegalArgumentException if authorizationUrl or scopes is null + */ public ImplicitOAuthFlow { Assert.checkNotNullParam("authorizationUrl", authorizationUrl); Assert.checkNotNullParam("scopes", scopes); diff --git a/spec/src/main/java/io/a2a/spec/IntegerJsonrpcId.java b/spec/src/main/java/io/a2a/spec/IntegerJsonrpcId.java index 2a01c1f50..a90fb87a9 100644 --- a/spec/src/main/java/io/a2a/spec/IntegerJsonrpcId.java +++ b/spec/src/main/java/io/a2a/spec/IntegerJsonrpcId.java @@ -1,4 +1,17 @@ package io.a2a.spec; +/** + * Represents an integer-based JSON-RPC request identifier. + * + * According to the JSON-RPC 2.0 specification, the ID can be a String, Number, or null. + * This class specifically handles integer (Number) identifiers. Numbers should not + * contain fractional parts as per the specification. + * + * The ID is used to correlate JSON-RPC requests with their corresponding responses. + * When a request is made, the same ID should be included in the response to allow + * the client to match responses to requests. + * + * @see JSON-RPC 2.0 Request Object + */ public class IntegerJsonrpcId { } diff --git a/spec/src/main/java/io/a2a/spec/InternalError.java b/spec/src/main/java/io/a2a/spec/InternalError.java index 47f1a332e..d60e0aeef 100644 --- a/spec/src/main/java/io/a2a/spec/InternalError.java +++ b/spec/src/main/java/io/a2a/spec/InternalError.java @@ -7,12 +7,34 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * Represents a JSON-RPC 2.0 Internal Error. + * + * This error indicates that an internal JSON-RPC error occurred on the server. + * This is a standard JSON-RPC error code as defined in the specification. + * The error signifies that the server encountered an unexpected condition + * that prevented it from fulfilling the request. + * + * Error code: -32603 + * Default message: "Internal Error" + * + * @see JSON-RPC 2.0 Error Object + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class InternalError extends JSONRPCError { + /** The standard JSON-RPC error code for internal errors */ public final static Integer DEFAULT_CODE = -32603; + /** + * Full constructor for InternalError. + * Used by Jackson for JSON deserialization. + * + * @param code the error code (defaults to -32603 if null) + * @param message the error message (defaults to "Internal Error" if null) + * @param data additional error data (optional) + */ @JsonCreator public InternalError( @JsonProperty("code") Integer code, @@ -24,6 +46,12 @@ public InternalError( data); } + /** + * Convenience constructor with custom message. + * Uses the default error code (-32603) and no additional data. + * + * @param message the custom error message + */ public InternalError(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 index 7b0476e2a..6b34d6004 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java @@ -8,14 +8,35 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * A2A specific error indicating agent returned invalid response for the current method. + * A2A-specific error indicating that an agent returned an invalid response for the current method. + * + * This error is used when an A2A agent returns a response that doesn't conform to the + * expected format or specification for the requested method. This could include: + * - Missing required fields in the response + * - Invalid data types or formats + * - Response structure that doesn't match the A2A specification + * - Malformed JSON or other parsing issues + * + * Error code: -32006 (A2A-specific extension) + * Default message: "Invalid agent response" + * + * This is an extension to the standard JSON-RPC error codes for A2A protocol-specific errors. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class InvalidAgentResponseError extends JSONRPCError { + /** The A2A-specific error code for invalid agent responses */ public final static Integer DEFAULT_CODE = -32006; + /** + * Full constructor for InvalidAgentResponseError. + * Used by Jackson for JSON deserialization. + * + * @param code the error code (defaults to -32006 if null) + * @param message the error message (defaults to "Invalid agent response" if null) + * @param data additional error data (optional) + */ @JsonCreator public InvalidAgentResponseError( @JsonProperty("code") Integer code, diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java index 69cd1fadc..4bbcd004f 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java @@ -7,12 +7,34 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * Represents a JSON-RPC 2.0 Invalid Params Error. + * + * This error indicates that the method parameters are invalid. This is a standard + * JSON-RPC error code used when the server receives a request with invalid parameter + * values, missing required parameters, or parameters that don't match the expected + * format or type for the requested method. + * + * Error code: -32602 + * Default message: "Invalid parameters" + * + * @see JSON-RPC 2.0 Error Object + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class InvalidParamsError extends JSONRPCError { + /** The standard JSON-RPC error code for invalid parameters */ public final static Integer DEFAULT_CODE = -32602; + /** + * Full constructor for InvalidParamsError. + * Used by Jackson for JSON deserialization. + * + * @param code the error code (defaults to -32602 if null) + * @param message the error message (defaults to "Invalid parameters" if null) + * @param data additional error data (optional) + */ @JsonCreator public InvalidParamsError( @JsonProperty("code") Integer code, @@ -24,6 +46,12 @@ public InvalidParamsError( data); } + /** + * Convenience constructor with custom message. + * Uses the default error code (-32602) and no additional data. + * + * @param message the custom error message + */ public InvalidParamsError(String message) { this(null, message, null); } diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsJsonMappingException.java b/spec/src/main/java/io/a2a/spec/InvalidParamsJsonMappingException.java index 41aa9a9bc..def0f5a84 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsJsonMappingException.java +++ b/spec/src/main/java/io/a2a/spec/InvalidParamsJsonMappingException.java @@ -1,11 +1,39 @@ package io.a2a.spec; +/** + * A specialized JSON mapping exception for invalid parameters in JSON-RPC requests. + * + * This exception extends {@link IdJsonMappingException} to provide specific handling + * for parameter validation errors during JSON deserialization of JSON-RPC requests. + * It carries the request ID to enable proper error correlation and response generation + * according to the JSON-RPC 2.0 specification. + * + * This exception is typically thrown when: + * - Required parameters are missing from the request + * - Parameter values cannot be deserialized to the expected types + * - Parameter validation fails during JSON processing + * + * @see IdJsonMappingException + */ public class InvalidParamsJsonMappingException extends IdJsonMappingException { + /** + * Constructs an InvalidParamsJsonMappingException with a message and request ID. + * + * @param msg the detail message explaining the parameter validation error + * @param id the JSON-RPC request ID associated with this exception + */ public InvalidParamsJsonMappingException(String msg, Object id) { super(msg, id); } + /** + * Constructs an InvalidParamsJsonMappingException with a message, cause, and request ID. + * + * @param msg the detail message explaining the parameter validation error + * @param cause the underlying cause of the mapping failure + * @param id the JSON-RPC request ID associated with this exception + */ public InvalidParamsJsonMappingException(String msg, Throwable cause, Object id) { super(msg, cause, id); } diff --git a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java index 17d3227dc..5066ba80a 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java @@ -7,16 +7,42 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * Represents a JSON-RPC 2.0 Invalid Request Error. + * + * This error indicates that the JSON sent is not a valid Request object. + * This is a standard JSON-RPC error code used when the server receives + * a request that doesn't conform to the JSON-RPC specification format. + * Common causes include: + * - Malformed JSON syntax + * - Missing required fields (jsonrpc, method) + * - Invalid field types or values + * - Request structure that doesn't match the JSON-RPC specification + * + * Error code: -32600 + * Default message: "Invalid Request" + * + * @see JSON-RPC 2.0 Error Object + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class InvalidRequestError extends JSONRPCError { + /** The standard JSON-RPC error code for invalid requests */ public final static Integer DEFAULT_CODE = -32600; public InvalidRequestError() { this(null, null, null); } + /** + * Full constructor for InvalidRequestError. + * Used by Jackson for JSON deserialization. + * + * @param code the error code (defaults to -32600 if null) + * @param message the error message (defaults to "Invalid Request" if null) + * @param data additional error data (optional) + */ @JsonCreator public InvalidRequestError( @JsonProperty("code") Integer code, @@ -28,6 +54,12 @@ public InvalidRequestError( data); } + /** + * Convenience constructor with custom message. + * Uses the default error code (-32600) and no additional data. + * + * @param message the custom error message + */ public InvalidRequestError(String message) { this(null, message, null); } diff --git a/spec/src/main/java/io/a2a/spec/JSONErrorResponse.java b/spec/src/main/java/io/a2a/spec/JSONErrorResponse.java index 3029f5394..89986a645 100644 --- a/spec/src/main/java/io/a2a/spec/JSONErrorResponse.java +++ b/spec/src/main/java/io/a2a/spec/JSONErrorResponse.java @@ -3,6 +3,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; +/** + * A simple record representing a JSON error response structure. + * + * This record encapsulates an error message in a response format, + * providing a lightweight wrapper around error information. + * It's used for cases where only the error message needs to be + * represented in JSON format. + * + * @param error the error message string containing error details + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record JSONErrorResponse(String error) { diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCErrorDeserializer.java b/spec/src/main/java/io/a2a/spec/JSONRPCErrorDeserializer.java index 229abf55d..ef0ed12a9 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCErrorDeserializer.java +++ b/spec/src/main/java/io/a2a/spec/JSONRPCErrorDeserializer.java @@ -10,16 +10,36 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +/** + * Custom Jackson deserializer for JSON-RPC error objects. + * + * This deserializer maps JSON-RPC error codes to their corresponding specific error classes. + * It reads the error code from the JSON and instantiates the appropriate error subclass + * based on a predefined mapping. If no specific error class is found for the code, + * it falls back to creating a generic {@link JSONRPCError} instance. + * + * The deserializer supports both standard JSON-RPC 2.0 error codes and A2A-specific + * extension error codes, ensuring proper type safety and error handling throughout + * the application. + * + * @see JSONRPCError + * @see StdDeserializer + */ public class JSONRPCErrorDeserializer extends StdDeserializer { + /** Map of error codes to their corresponding constructor functions */ private static final Map> ERROR_MAP = new HashMap<>(); + // Static initialization block to populate the error code mapping static { + // Standard JSON-RPC 2.0 error codes ERROR_MAP.put(JSONParseError.DEFAULT_CODE, JSONParseError::new); ERROR_MAP.put(InvalidRequestError.DEFAULT_CODE, InvalidRequestError::new); ERROR_MAP.put(MethodNotFoundError.DEFAULT_CODE, MethodNotFoundError::new); ERROR_MAP.put(InvalidParamsError.DEFAULT_CODE, InvalidParamsError::new); ERROR_MAP.put(InternalError.DEFAULT_CODE, InternalError::new); + + // A2A-specific extension error codes ERROR_MAP.put(PushNotificationNotSupportedError.DEFAULT_CODE, PushNotificationNotSupportedError::new); ERROR_MAP.put(UnsupportedOperationError.DEFAULT_CODE, UnsupportedOperationError::new); ERROR_MAP.put(ContentTypeNotSupportedError.DEFAULT_CODE, ContentTypeNotSupportedError::new); @@ -28,14 +48,36 @@ public class JSONRPCErrorDeserializer extends StdDeserializer { ERROR_MAP.put(TaskNotFoundError.DEFAULT_CODE, TaskNotFoundError::new); } + /** + * Default constructor for JSONRPCErrorDeserializer. + */ public JSONRPCErrorDeserializer() { this(null); } + /** + * Constructor with value class parameter. + * + * @param vc the value class for deserialization + */ public JSONRPCErrorDeserializer(Class vc) { super(vc); } + /** + * Deserializes a JSON-RPC error object from JSON. + * + * This method reads the JSON representation of an error and creates the appropriate + * error instance based on the error code. It extracts the code, message, and optional + * data fields from the JSON and uses the error code to determine which specific + * error class to instantiate. + * + * @param jsonParser the JSON parser containing the error data + * @param context the deserialization context + * @return the deserialized JSONRPCError instance + * @throws IOException if an I/O error occurs during parsing + * @throws JsonProcessingException if JSON processing fails + */ @Override public JSONRPCError deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { @@ -52,8 +94,24 @@ public JSONRPCError deserialize(JsonParser jsonParser, DeserializationContext co } } + /** + * Functional interface for three-parameter constructor functions. + * + * @param the type of the first parameter + * @param the type of the second parameter + * @param the type of the third parameter + * @param the return type + */ @FunctionalInterface private interface TriFunction { + /** + * Applies this function to the given arguments. + * + * @param a the first function argument + * @param b the second function argument + * @param c the third function argument + * @return the function result + */ R apply(A a, B b, C c); } } diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCErrorResponse.java b/spec/src/main/java/io/a2a/spec/JSONRPCErrorResponse.java index ea7846655..085c83c5d 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCErrorResponse.java +++ b/spec/src/main/java/io/a2a/spec/JSONRPCErrorResponse.java @@ -8,12 +8,33 @@ import io.a2a.util.Assert; /** - * A JSON RPC error response. + * Represents a JSON-RPC 2.0 error response. + * + * This class extends {@link JSONRPCResponse} to provide a complete JSON-RPC error response + * structure according to the JSON-RPC 2.0 specification. An error response contains + * the standard JSON-RPC fields (jsonrpc, id) along with an error object that includes + * the error code, message, and optional data. + * + * The response is used when a JSON-RPC request cannot be processed successfully, + * providing detailed error information to the client. + * + * @see JSONRPCResponse + * @see JSONRPCError + * @see JSON-RPC 2.0 Response Object */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class JSONRPCErrorResponse extends JSONRPCResponse { + /** + * Creates a new JSONRPCErrorResponse with all parameters. + * + * @param jsonrpc the JSON-RPC version (should be "2.0") + * @param id the request identifier that this response corresponds to + * @param result the result field (always null for error responses) + * @param error the error object containing error details + * @throws IllegalArgumentException if error is null + */ @JsonCreator public JSONRPCErrorResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("result") Void result, @JsonProperty("error") JSONRPCError error) { @@ -21,10 +42,23 @@ public JSONRPCErrorResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProper Assert.checkNotNullParam("error", error); } + /** + * Creates a new JSONRPCErrorResponse with the specified id and error. + * The jsonrpc version will be set to null and result will be null. + * + * @param id the request identifier that this response corresponds to + * @param error the error object containing error details + */ public JSONRPCErrorResponse(Object id, JSONRPCError error) { this(null, id, null, error); } + /** + * Creates a new JSONRPCErrorResponse with only the error object. + * The jsonrpc version, id, and result will all be set to null. + * + * @param error the error object containing error details + */ public JSONRPCErrorResponse(JSONRPCError error) { this(null, null, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCErrorSerializer.java b/spec/src/main/java/io/a2a/spec/JSONRPCErrorSerializer.java index 87b427548..3d319417d 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCErrorSerializer.java +++ b/spec/src/main/java/io/a2a/spec/JSONRPCErrorSerializer.java @@ -6,16 +6,53 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; +/** + * Custom Jackson serializer for JSON-RPC error objects. + * + * This serializer ensures that JSON-RPC errors are serialized according to the + * JSON-RPC 2.0 specification format. It writes the error as a JSON object with + * the required "code" and "message" fields, and an optional "data" field if present. + * + * The serializer handles all subclasses of {@link JSONRPCError} uniformly, + * ensuring consistent error format across the application. + * + * @see JSONRPCError + * @see StdSerializer + * @see JSON-RPC 2.0 Error Object + */ public class JSONRPCErrorSerializer extends StdSerializer { + /** + * Default constructor for JSONRPCErrorSerializer. + */ public JSONRPCErrorSerializer() { this(null); } - public JSONRPCErrorSerializer(Class vc) { - super(vc); + /** + * Constructor with type parameter. + * + * @param t the class type for serialization + */ + public JSONRPCErrorSerializer(Class t) { + super(t); } + /** + * Serializes a JSON-RPC error object to JSON format. + * + * This method writes the error as a JSON object containing: + * - "code": the numeric error code (required) + * - "message": the error message string (required) + * - "data": additional error data (optional, only included if not null) + * + * The output format conforms to the JSON-RPC 2.0 specification for error objects. + * + * @param value the JSONRPCError instance to serialize + * @param gen the JSON generator to write to + * @param provider the serializer provider + * @throws IOException if an I/O error occurs during serialization + */ @Override public void serialize(JSONRPCError value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCMessage.java b/spec/src/main/java/io/a2a/spec/JSONRPCMessage.java index 20d3a117a..fdc9a570b 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCMessage.java +++ b/spec/src/main/java/io/a2a/spec/JSONRPCMessage.java @@ -1,13 +1,40 @@ package io.a2a.spec; /** - * Represents a JSONRPC message. + * Base interface for all JSON-RPC 2.0 messages. + * + * This sealed interface defines the common structure for JSON-RPC messages, + * which includes both requests and responses. According to the JSON-RPC 2.0 + * specification, all messages must contain: + * - A "jsonrpc" field specifying the protocol version ("2.0") + * - An "id" field for request/response correlation (except for notifications) + * + * This interface is sealed to ensure type safety and restrict implementations + * to only the permitted subtypes: {@link JSONRPCRequest} and {@link JSONRPCResponse}. + * + * @see JSONRPCRequest + * @see JSONRPCResponse + * @see JSON-RPC 2.0 Specification */ public sealed interface JSONRPCMessage permits JSONRPCRequest, JSONRPCResponse { + /** The JSON-RPC protocol version constant */ String JSONRPC_VERSION = "2.0"; + /** + * Gets the JSON-RPC protocol version. + * + * @return the protocol version string (should be "2.0") + */ String getJsonrpc(); - Object getId(); + /** + * Gets the message identifier. + * + * The identifier is used to correlate requests with responses. + * For notifications, this may be null. + * + * @return the message identifier, or null for notifications + */ + Object getId(); } diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCRequest.java b/spec/src/main/java/io/a2a/spec/JSONRPCRequest.java index a88de90f1..a48d318e6 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCRequest.java +++ b/spec/src/main/java/io/a2a/spec/JSONRPCRequest.java @@ -8,20 +8,55 @@ import io.a2a.util.Assert; /** - * Represents a JSONRPC request. + * Abstract base class for JSON-RPC 2.0 request messages. + * + * This sealed class represents a JSON-RPC request according to the JSON-RPC 2.0 + * specification. A request contains: + * - "jsonrpc": the protocol version ("2.0") + * - "method": the name of the method to be invoked + * - "params": the parameter values (optional) + * - "id": the request identifier for correlation with responses (optional for notifications) + * + * This class is sealed to ensure type safety and restrict implementations to + * the permitted subtypes: {@link NonStreamingJSONRPCRequest} and {@link StreamingJSONRPCRequest}. + * + * @param the type of the parameters object + * @see NonStreamingJSONRPCRequest + * @see StreamingJSONRPCRequest + * @see JSONRPCMessage + * @see JSON-RPC 2.0 Request Object */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public abstract sealed class JSONRPCRequest implements JSONRPCMessage permits NonStreamingJSONRPCRequest, StreamingJSONRPCRequest { + /** The JSON-RPC protocol version */ protected String jsonrpc; + + /** The request identifier for correlation with responses */ protected Object id; + + /** The name of the method to be invoked */ protected String method; + + /** The parameter values for the method invocation */ protected T params; + /** + * Default constructor for JSON deserialization. + */ public JSONRPCRequest() { } + /** + * Constructs a new JSON-RPC request with the specified parameters. + * + * @param jsonrpc the JSON-RPC protocol version (must not be null) + * @param id the request identifier for correlation with responses (can be null for notifications) + * @param method the name of the method to be invoked (must not be null) + * @param params the parameter values for the method invocation (can be null) + * @throws IllegalArgumentException if jsonrpc or method is null, or if id is not null, string, or integer + */ public JSONRPCRequest(String jsonrpc, Object id, String method, T params) { Assert.checkNotNullParam("jsonrpc", jsonrpc); Assert.checkNotNullParam("method", method); @@ -32,20 +67,40 @@ public JSONRPCRequest(String jsonrpc, Object id, String method, T params) { this.params = params; } + /** + * Returns the JSON-RPC protocol version. + * + * @return the JSON-RPC protocol version (typically "2.0") + */ @Override public String getJsonrpc() { return this.jsonrpc; } + /** + * Returns the request identifier for correlation with responses. + * + * @return the request identifier, or null for notification requests + */ @Override public Object getId() { return this.id; } + /** + * Returns the name of the method to be invoked. + * + * @return the method name + */ public String getMethod() { return this.method; } + /** + * Returns the parameter values for the method invocation. + * + * @return the parameters object, or null if no parameters are provided + */ public T getParams() { return this.params; } diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCResponse.java b/spec/src/main/java/io/a2a/spec/JSONRPCResponse.java index 3a382b1a7..f5fdaca3f 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCResponse.java +++ b/spec/src/main/java/io/a2a/spec/JSONRPCResponse.java @@ -9,7 +9,15 @@ import io.a2a.util.Assert; /** - * Represents a JSONRPC response. + * Represents a JSON-RPC 2.0 response object as defined in the A2A protocol specification. + * This is an abstract sealed class that serves as the base for all JSON-RPC response types. + * + *

A JSON-RPC response must contain either a result (for success) or an error (for failure), + * but never both. The response also includes the JSON-RPC version and an optional ID that + * matches the corresponding request.

+ * + *

This class enforces the JSON-RPC 2.0 specification constraints and provides common + * functionality for all response types in the A2A protocol.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -17,11 +25,21 @@ public abstract sealed class JSONRPCResponse implements JSONRPCMessage permit GetTaskResponse, CancelTaskResponse, SetTaskPushNotificationConfigResponse, GetTaskPushNotificationConfigResponse, SendMessageResponse, DeleteTaskPushNotificationConfigResponse, ListTaskPushNotificationConfigResponse, JSONRPCErrorResponse { + /** The JSON-RPC protocol version, must be "2.0" */ protected String jsonrpc; + + /** The request identifier, can be a string, number, or null */ protected Object id; + + /** The result object for successful responses, null for error responses */ protected T result; + + /** The error object for failed responses, null for successful responses */ protected JSONRPCError error; + /** + * Default constructor for JSON deserialization. + */ public JSONRPCResponse() { } @@ -42,18 +60,38 @@ public JSONRPCResponse(String jsonrpc, Object id, T result, JSONRPCError error, this.error = error; } + /** + * Gets the JSON-RPC protocol version. + * + * @return the protocol version ("2.0") + */ public String getJsonrpc() { return this.jsonrpc; } + /** + * Gets the request identifier. + * + * @return the request ID (string, number, or null) + */ public Object getId() { return this.id; } + /** + * Gets the result object for successful responses. + * + * @return the result object, or null if this is an error response + */ public T getResult() { return this.result; } + /** + * Gets the error object for failed responses. + * + * @return the error object, or null if this is a successful response + */ public JSONRPCError getError() { return this.error; } diff --git a/spec/src/main/java/io/a2a/spec/JsonrpcId.java b/spec/src/main/java/io/a2a/spec/JsonrpcId.java index e4db4b458..9aa5e965b 100644 --- a/spec/src/main/java/io/a2a/spec/JsonrpcId.java +++ b/spec/src/main/java/io/a2a/spec/JsonrpcId.java @@ -1,4 +1,25 @@ package io.a2a.spec; +/** + * Marker interface for JSON-RPC request identifiers. + * + * According to the JSON-RPC 2.0 specification, the request identifier can be: + * - A String + * - A Number (integer or decimal) + * - null (for notification requests) + * + * This interface serves as a type marker to identify classes that can be used + * as JSON-RPC request identifiers. Implementations should handle the specific + * type of identifier (string, integer, etc.) and provide appropriate serialization + * and deserialization behavior. + * + * The identifier is used to correlate JSON-RPC requests with their corresponding + * responses, allowing clients to match responses to the original requests in + * asynchronous communication scenarios. + * + * @see JSON-RPC 2.0 Request Object + * @see IntegerJsonrpcId + * @see StringJsonrpcId + */ public interface JsonrpcId { } diff --git a/spec/src/main/java/io/a2a/spec/Message.java b/spec/src/main/java/io/a2a/spec/Message.java index f17646a0f..960b909e2 100644 --- a/spec/src/main/java/io/a2a/spec/Message.java +++ b/spec/src/main/java/io/a2a/spec/Message.java @@ -13,7 +13,11 @@ import io.a2a.util.Assert; /** - * An A2A message. + * Represents a message in the A2A protocol communication. + * A message contains content parts, metadata, and context information for agent-to-agent communication. + * + * This class implements both EventKind and StreamingEventKind interfaces to support + * different types of message processing in the A2A framework. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -22,20 +26,77 @@ public final class Message implements EventKind, StreamingEventKind { public static final TypeReference TYPE_REFERENCE = new TypeReference<>() {}; public static final String MESSAGE = "message"; + /** + * The role of the entity that created this message (user or agent). + */ private final Role role; + + /** + * The content parts that make up this message. + * Each part can be text, file, data, or other content types. + */ private final List> parts; + + /** + * Unique identifier for this message. + */ private final String messageId; + + /** + * Identifier for the conversation context this message belongs to. + */ private String contextId; + + /** + * Identifier for the task this message is associated with. + */ private String taskId; + + /** + * Additional metadata associated with this message. + * Can contain custom properties specific to the implementation. + */ private final Map metadata; + + /** + * The kind/type of this message, always "message" for Message instances. + */ private final String kind; + + /** + * List of task IDs that this message references. + * Used for establishing relationships between tasks. + */ private final List referenceTaskIds; + /** + * Constructs a new Message with the specified properties. + * + * @param role the role of the entity that created this message + * @param parts the content parts that make up this message + * @param messageId unique identifier for this message + * @param contextId identifier for the conversation context + * @param taskId identifier for the associated task + * @param referenceTaskIds list of task IDs that this message references + * @param metadata additional metadata for this message + */ public Message(Role role, List> parts, String messageId, String contextId, String taskId, List referenceTaskIds, Map metadata) { this(role, parts, messageId, contextId, taskId, referenceTaskIds, metadata, MESSAGE); } + /** + * JSON constructor for creating Message instances from JSON data. + * + * @param role the role of the entity that created this message + * @param parts the content parts that make up this message + * @param messageId unique identifier for this message + * @param contextId identifier for the conversation context + * @param taskId identifier for the associated task + * @param referenceTaskIds list of task IDs that this message references + * @param metadata additional metadata for this message + * @param kind the kind/type of this message + */ @JsonCreator public Message(@JsonProperty("role") Role role, @JsonProperty("parts") List> parts, @JsonProperty("messageId") String messageId, @JsonProperty("contextId") String contextId, @@ -61,49 +122,109 @@ public Message(@JsonProperty("role") Role role, @JsonProperty("parts") List> getParts() { return parts; } + /** + * Gets the unique identifier for this message. + * + * @return the message ID + */ public String getMessageId() { return messageId; } + /** + * Gets the identifier for the conversation context this message belongs to. + * + * @return the context ID + */ public String getContextId() { return contextId; } + /** + * Gets the identifier for the task this message is associated with. + * + * @return the task ID + */ public String getTaskId() { return taskId; } + /** + * Gets the additional metadata associated with this message. + * + * @return the metadata map + */ public Map getMetadata() { return metadata; } + /** + * Sets the identifier for the task this message is associated with. + * + * @param taskId the task ID to set + */ public void setTaskId(String taskId) { this.taskId = taskId; } + /** + * Sets the identifier for the conversation context this message belongs to. + * + * @param contextId the context ID to set + */ public void setContextId(String contextId) { this.contextId = contextId; } + /** + * Gets the list of task IDs that this message references. + * + * @return the list of reference task IDs + */ public List getReferenceTaskIds() { return referenceTaskIds; } + /** + * Gets the kind/type of this message. + * + * @return the message kind, always "message" for Message instances + */ @Override public String getKind() { return kind; } + /** + * Enumeration representing the role of the entity that created a message. + */ public enum Role { + /** + * Represents a message created by a user/human. + */ USER("user"), + + /** + * Represents a message created by an agent/AI system. + */ AGENT("agent"); private String role; @@ -118,6 +239,9 @@ public String asString() { } } + /** + * Builder class for constructing {@link Message} instances. + */ public static class Builder { private Role role; @@ -128,9 +252,17 @@ public static class Builder { private List referenceTaskIds; private Map metadata; + /** + * Default constructor for creating a new Builder instance. + */ public Builder() { } + /** + * Constructor for creating a Builder instance from an existing Message. + * + * @param message the message to copy properties from + */ public Builder(Message message) { role = message.role; parts = message.parts; @@ -141,46 +273,99 @@ public Builder(Message message) { metadata = message.metadata; } + /** + * Sets the role of the entity that created this message. + * + * @param role the role (USER or AGENT) + * @return this builder instance + */ public Builder role(Role role) { this.role = role; return this; } + /** + * Sets the content parts that make up this message. + * + * @param parts the list of content parts + * @return this builder instance + */ public Builder parts(List> parts) { this.parts = parts; return this; } + /** + * Sets the content parts that make up this message using varargs. + * + * @param parts the content parts as varargs + * @return this builder instance + */ public Builder parts(Part...parts) { this.parts = List.of(parts); return this; } + /** + * Sets the unique identifier for this message. + * + * @param messageId the message ID + * @return this builder instance + */ public Builder messageId(String messageId) { this.messageId = messageId; return this; } + /** + * Sets the identifier for the conversation context this message belongs to. + * + * @param contextId the context ID + * @return this builder instance + */ public Builder contextId(String contextId) { this.contextId = contextId; return this; } + /** + * Sets the identifier for the task this message is associated with. + * + * @param taskId the task ID + * @return this builder instance + */ public Builder taskId(String taskId) { this.taskId = taskId; return this; } + /** + * Sets the list of task IDs that this message references. + * + * @param referenceTaskIds the list of reference task IDs + * @return this builder instance + */ public Builder referenceTaskIds(List referenceTaskIds) { this.referenceTaskIds = referenceTaskIds; return this; } + /** + * Sets the additional metadata associated with this message. + * + * @param metadata the metadata map + * @return this builder instance + */ public Builder metadata(Map metadata) { this.metadata = metadata; return this; } + /** + * Builds and returns a new {@link Message} instance with the configured properties. + * + * @return a new Message instance + */ public Message build() { return new Message(role, parts, messageId, contextId, taskId, referenceTaskIds, metadata); } diff --git a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java index f34af9dcf..f376ec36e 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java +++ b/spec/src/main/java/io/a2a/spec/MessageSendConfiguration.java @@ -8,16 +8,33 @@ import io.a2a.util.Assert; /** - * Represents the configuration of the message to be sent. + * Represents the configuration parameters for sending a message in the A2A protocol. + * This configuration controls various aspects of message delivery and response handling. * - * If {@code blocking} is true, {@code pushNotification} is ignored. - * Both {@code blocking} and {@code pushNotification} are ignored in streaming interactions. + *

The configuration includes:

+ *
    + *
  • Accepted output modes (MIME types) that the client can handle
  • + *
  • History length for retrieving previous messages in the conversation
  • + *
  • Push notification settings for asynchronous updates
  • + *
  • Blocking behavior for synchronous vs asynchronous processing
  • + *
+ * + *

Important behavioral notes:

+ *
    + *
  • If {@code blocking} is true, {@code pushNotification} is ignored
  • + *
  • Both {@code blocking} and {@code pushNotification} are ignored in streaming interactions
  • + *
*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record MessageSendConfiguration(List acceptedOutputModes, Integer historyLength, PushNotificationConfig pushNotification, boolean blocking) { + /** + * Compact constructor that validates the configuration parameters. + * + * @throws IllegalArgumentException if acceptedOutputModes is null or historyLength is negative + */ public MessageSendConfiguration { Assert.checkNotNullParam("acceptedOutputModes", acceptedOutputModes); if (historyLength != null && historyLength < 0) { @@ -25,32 +42,73 @@ public record MessageSendConfiguration(List acceptedOutputModes, Integer } } + /** + * Builder class for constructing MessageSendConfiguration instances. + * Provides a fluent API for setting configuration parameters. + */ public static class Builder { + /** List of accepted output MIME types */ List acceptedOutputModes; + + /** Number of messages to retrieve from history */ Integer historyLength; + + /** Push notification configuration */ PushNotificationConfig pushNotification; + + /** Whether to use blocking behavior */ boolean blocking; + /** + * Sets the list of MIME types that the client accepts as output. + * + * @param acceptedOutputModes list of accepted MIME types (required) + * @return this builder instance for method chaining + */ public Builder acceptedOutputModes(List acceptedOutputModes) { this.acceptedOutputModes = acceptedOutputModes; return this; } + /** + * Sets the push notification configuration for asynchronous updates. + * + * @param pushNotification the push notification configuration (ignored if blocking is true) + * @return this builder instance for method chaining + */ public Builder pushNotification(PushNotificationConfig pushNotification) { this.pushNotification = pushNotification; return this; } + /** + * Sets the number of recent messages to retrieve from conversation history. + * + * @param historyLength the number of messages to retrieve (null for no history, must be non-negative) + * @return this builder instance for method chaining + */ public Builder historyLength(Integer historyLength) { this.historyLength = historyLength; return this; } + /** + * Sets whether the client should use blocking behavior. + * + * @param blocking true for synchronous blocking behavior, false for asynchronous handling + * @return this builder instance for method chaining + */ public Builder blocking(boolean blocking) { this.blocking = blocking; return this; } + /** + * Builds and returns a new MessageSendConfiguration instance. + * + * @return a new MessageSendConfiguration with the specified parameters + * @throws IllegalArgumentException if the configuration is invalid + */ public MessageSendConfiguration build() { return new MessageSendConfiguration(acceptedOutputModes, historyLength, pushNotification, blocking); } diff --git a/spec/src/main/java/io/a2a/spec/MessageSendParams.java b/spec/src/main/java/io/a2a/spec/MessageSendParams.java index a217539b1..6cca5dae0 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendParams.java +++ b/spec/src/main/java/io/a2a/spec/MessageSendParams.java @@ -7,37 +7,84 @@ import io.a2a.util.Assert; /** - * Used to specify parameters when creating a message. + * Represents the parameters for sending a message in the A2A protocol. + * This class encapsulates all the necessary information required to send a message, + * including the message content, configuration settings, and metadata. + * + *

The parameters include:

+ *
    + *
  • The actual message content to be sent
  • + *
  • Configuration settings that control message delivery behavior
  • + *
  • Additional metadata associated with the message
  • + *
*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record MessageSendParams(Message message, MessageSendConfiguration configuration, Map metadata) { + /** + * Compact constructor that validates the message send parameters. + * + * @throws IllegalArgumentException if message is null + */ public MessageSendParams { Assert.checkNotNullParam("message", message); } + /** + * Builder class for constructing MessageSendParams instances. + * Provides a fluent API for setting message parameters. + */ public static class Builder { + /** The message content to be sent */ Message message; + + /** The message send configuration */ MessageSendConfiguration configuration; + + /** Additional metadata for the message */ Map metadata; + /** + * Sets the message content to be sent. + * + * @param message the message content (required) + * @return this builder instance for method chaining + */ public Builder message(Message message) { this.message = message; return this; } + /** + * Sets the configuration for message sending. + * + * @param configuration the message send configuration (optional) + * @return this builder instance for method chaining + */ public Builder configuration(MessageSendConfiguration configuration) { this.configuration = configuration; return this; } + /** + * Sets the metadata for the message. + * + * @param metadata additional metadata associated with the message (optional) + * @return this builder instance for method chaining + */ public Builder metadata(Map metadata) { this.metadata = metadata; return this; } + /** + * Builds and returns a new MessageSendParams instance. + * + * @return a new MessageSendParams with the specified parameters + * @throws IllegalArgumentException if message is null + */ public MessageSendParams build() { return new MessageSendParams(message, configuration, metadata); } diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java index a8d9d9289..cb3fa0840 100644 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java @@ -7,12 +7,35 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * Represents a JSON-RPC error that occurs when a requested method is not found. + * This error is part of the A2A protocol's error handling mechanism and follows + * the JSON-RPC 2.0 specification for method not found errors. + * + *

This error is typically returned when:

+ *
    + *
  • The requested method name does not exist on the server
  • + *
  • The method is not available in the current context
  • + *
  • The method has been deprecated or removed
  • + *
+ * + *

According to JSON-RPC 2.0, this error uses code -32601.

+ */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class MethodNotFoundError extends JSONRPCError { + /** The default JSON-RPC error code for method not found errors */ public final static Integer DEFAULT_CODE = -32601; + /** + * Constructs a new MethodNotFoundError with the specified error details. + * This constructor is used by Jackson for JSON deserialization. + * + * @param code the JSON-RPC error code (defaults to -32601 if null) + * @param message a human-readable error message (defaults to "Method not found" if null) + * @param data additional error data providing context (can be null) + */ @JsonCreator public MethodNotFoundError( @JsonProperty("code") Integer code, @@ -24,6 +47,10 @@ public MethodNotFoundError( data); } + /** + * Constructs a new MethodNotFoundError with default values. + * Uses the default error code (-32601) and message ("Method not found"). + */ public MethodNotFoundError() { this(DEFAULT_CODE, null, null); } diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundJsonMappingException.java b/spec/src/main/java/io/a2a/spec/MethodNotFoundJsonMappingException.java index 7bd167ad1..1fe753a44 100644 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundJsonMappingException.java +++ b/spec/src/main/java/io/a2a/spec/MethodNotFoundJsonMappingException.java @@ -1,11 +1,40 @@ package io.a2a.spec; +/** + * Exception thrown during JSON deserialization when a requested method is not found. + * This exception is specifically used in the context of JSON-RPC request deserialization + * when the method field contains an unrecognized or unsupported method name. + * + *

This exception extends {@code IdJsonMappingException} to preserve the request ID + * from the original JSON-RPC request, which is essential for proper error response + * generation according to the JSON-RPC 2.0 specification.

+ * + *

Common scenarios where this exception is thrown:

+ *
    + *
  • The method name in the JSON-RPC request is not recognized
  • + *
  • The method is not supported by the current deserializer
  • + *
  • The method name is malformed or invalid
  • + *
+ */ public class MethodNotFoundJsonMappingException extends IdJsonMappingException { + /** + * Constructs a new MethodNotFoundJsonMappingException with the specified message and request ID. + * + * @param msg the detail message explaining the method not found error + * @param id the request ID from the original JSON-RPC request (can be null) + */ public MethodNotFoundJsonMappingException(String msg, Object id) { super(msg, id); } + /** + * Constructs a new MethodNotFoundJsonMappingException with the specified message, cause, and request ID. + * + * @param msg the detail message explaining the method not found error + * @param cause the underlying cause of the exception (can be null) + * @param id the request ID from the original JSON-RPC request (can be null) + */ public MethodNotFoundJsonMappingException(String msg, Throwable cause, Object id) { super(msg, cause, id); } diff --git a/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequest.java b/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequest.java index 1c0a696e7..ad7d296e9 100644 --- a/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequest.java +++ b/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequest.java @@ -5,7 +5,30 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; /** - * Represents a non-streaming JSON-RPC request. + * Represents a non-streaming JSON-RPC request in the A2A protocol. + * This abstract sealed class serves as the base for all JSON-RPC requests that follow + * a traditional request-response pattern without streaming capabilities. + * + *

Non-streaming requests are used for operations that:

+ *
    + *
  • Expect a single, complete response
  • + *
  • Do not require real-time updates or incremental data delivery
  • + *
  • Follow the standard JSON-RPC 2.0 request-response model
  • + *
+ * + *

This class is sealed and permits only the following concrete implementations:

+ *
    + *
  • {@link GetTaskRequest} - for retrieving task information
  • + *
  • {@link CancelTaskRequest} - for canceling running tasks
  • + *
  • {@link SetTaskPushNotificationConfigRequest} - for configuring push notifications
  • + *
  • {@link GetTaskPushNotificationConfigRequest} - for retrieving push notification config
  • + *
  • {@link SendMessageRequest} - for sending messages without streaming
  • + *
+ * + *

The class uses a custom deserializer ({@link NonStreamingJSONRPCRequestDeserializer}) + * to properly handle the polymorphic deserialization based on the method field.

+ * + * @param the type of the request parameters */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequestDeserializer.java b/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequestDeserializer.java index c97c524c5..d8a762a95 100644 --- a/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequestDeserializer.java +++ b/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequestDeserializer.java @@ -9,14 +9,34 @@ public class NonStreamingJSONRPCRequestDeserializer extends JSONRPCRequestDeserializerBase> { + /** + * Default constructor for the deserializer. + * Calls the parameterized constructor with null value class. + */ public NonStreamingJSONRPCRequestDeserializer() { this(null); } + /** + * Constructs a deserializer with the specified value class. + * + * @param vc the value class for deserialization (can be null) + */ public NonStreamingJSONRPCRequestDeserializer(Class vc) { super(vc); } + /** + * Deserializes a JSON-RPC request into the appropriate non-streaming request type + * based on the method field. + * + * @param jsonParser the JSON parser containing the request data + * @param context the deserialization context + * @return the deserialized non-streaming JSON-RPC request + * @throws IOException if an I/O error occurs during parsing + * @throws JsonProcessingException if the JSON content is malformed + * @throws MethodNotFoundJsonMappingException if the method is not recognized + */ @Override public NonStreamingJSONRPCRequest deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { diff --git a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java b/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java index 10141ffb7..285e68b53 100644 --- a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java @@ -8,21 +8,67 @@ import io.a2a.util.Assert; /** - * Represents an OAuth2 security scheme. + * Represents an OAuth 2.0 security scheme configuration for the A2A protocol. + * This class defines the OAuth 2.0 authentication requirements and supported flows + * for accessing an A2A agent's endpoints. + * + *

OAuth 2.0 is a widely-used authorization framework that enables applications + * to obtain limited access to user accounts. In the A2A context, it allows agents + * to securely authenticate and authorize access to their services.

+ * + *

The security scheme includes:

+ *
    + *
  • Supported OAuth flows (authorization code, client credentials, implicit, password)
  • + *
  • Optional description of the authentication requirements
  • + *
  • Type identifier (always "oauth2" for OAuth 2.0 schemes)
  • + *
+ * + *

This implementation follows the OpenAPI Security Scheme Object specification + * for OAuth 2.0 security schemes, ensuring compatibility with standard OAuth 2.0 + * implementations and tooling.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class OAuth2SecurityScheme implements SecurityScheme { public static final String OAUTH2 = "oauth2"; + + /** + * The OAuth flows supported by this security scheme. + * Defines the available OAuth 2.0 grant types and their configurations. + */ private final OAuthFlows flows; + + /** + * Optional description of the OAuth 2.0 security scheme. + * Provides human-readable information about the authentication requirements. + */ private final String description; + + /** + * The type of security scheme, always "oauth2" for OAuth 2.0. + */ private final String type; + /** + * Constructs an OAuth 2.0 security scheme with flows and description. + * + * @param flows the OAuth flows configuration (must not be null) + * @param description optional description of the security scheme (can be null) + */ public OAuth2SecurityScheme(OAuthFlows flows, String description) { this(flows, description, OAUTH2); } + /** + * Constructs an OAuth 2.0 security scheme with all parameters. + * This constructor is used for JSON deserialization. + * + * @param flows the OAuth flows configuration (must not be null) + * @param description optional description of the security scheme (can be null) + * @param type the security scheme type (must be "oauth2") + * @throws IllegalArgumentException if flows is null or type is not "oauth2" + */ @JsonCreator public OAuth2SecurityScheme(@JsonProperty("flows") OAuthFlows flows, @JsonProperty("description") String description, @JsonProperty("type") String type) { @@ -35,33 +81,77 @@ public OAuth2SecurityScheme(@JsonProperty("flows") OAuthFlows flows, @JsonProper this.type = type; } + /** + * Returns the optional description of this security scheme. + * + * @return the description, or null if not provided + */ @Override public String getDescription() { return description; } + /** + * Returns the OAuth flows configuration for this security scheme. + * + * @return the OAuth flows configuration + */ public OAuthFlows getFlows() { return flows; } + /** + * Returns the type of this security scheme. + * + * @return always "oauth2" for OAuth 2.0 security schemes + */ public String getType() { return type; } + /** + * Builder class for constructing OAuth2SecurityScheme instances. + * Provides a fluent API for setting optional properties. + */ public static class Builder { + /** + * The OAuth flows configuration for the security scheme. + */ private OAuthFlows flows; + + /** + * Optional description of the security scheme. + */ private String description; + /** + * Sets the OAuth flows configuration. + * + * @param flows the OAuth flows configuration + * @return this builder instance for method chaining + */ public Builder flows(OAuthFlows flows) { this.flows = flows; return this; } + /** + * Sets the optional description for the security scheme. + * + * @param description the description of the security scheme + * @return this builder instance for method chaining + */ public Builder description(String description) { this.description = description; return this; } + /** + * Builds and returns a new OAuth2SecurityScheme instance. + * + * @return a new OAuth2SecurityScheme with the configured properties + * @throws IllegalArgumentException if flows is null + */ public OAuth2SecurityScheme build() { return new OAuth2SecurityScheme(flows, description); } diff --git a/spec/src/main/java/io/a2a/spec/OAuthFlows.java b/spec/src/main/java/io/a2a/spec/OAuthFlows.java index fcd89bc3d..de82b0ec2 100644 --- a/spec/src/main/java/io/a2a/spec/OAuthFlows.java +++ b/spec/src/main/java/io/a2a/spec/OAuthFlows.java @@ -4,39 +4,93 @@ import com.fasterxml.jackson.annotation.JsonInclude; /** - * Allows configuration of the supported OAuth Flows. + * Represents the configuration for supported OAuth 2.0 flows in the A2A protocol. + * This record defines the various OAuth 2.0 grant types that an agent supports + * for authentication and authorization. + * + *

OAuth flows define how clients can obtain access tokens to authenticate + * with the agent. Different flows are suitable for different types of applications:

+ *
    + *
  • Authorization Code - for web applications with server-side components
  • + *
  • Client Credentials - for machine-to-machine authentication
  • + *
  • Implicit - for single-page applications (deprecated in OAuth 2.1)
  • + *
  • Password - for trusted applications (not recommended for new implementations)
  • + *
+ * + *

This implementation follows the OpenAPI OAuth Flows Object specification, + * ensuring compatibility with standard OAuth 2.0 implementations and tooling.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record OAuthFlows(AuthorizationCodeOAuthFlow authorizationCode, ClientCredentialsOAuthFlow clientCredentials, ImplicitOAuthFlow implicit, PasswordOAuthFlow password) { + /** + * Builder class for constructing OAuthFlows instances. + * Provides a fluent API for configuring supported OAuth 2.0 flows. + */ public static class Builder { + /** Configuration for the authorization code flow */ private AuthorizationCodeOAuthFlow authorizationCode; + + /** Configuration for the client credentials flow */ private ClientCredentialsOAuthFlow clientCredentials; + + /** Configuration for the implicit flow */ private ImplicitOAuthFlow implicit; + + /** Configuration for the password flow */ private PasswordOAuthFlow password; + /** + * Sets the authorization code flow configuration. + * + * @param authorizationCode the authorization code flow configuration + * @return this builder instance 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 configuration + * @return this builder instance for method chaining + */ public Builder clientCredentials(ClientCredentialsOAuthFlow clientCredentials) { this.clientCredentials = clientCredentials; return this; } + /** + * Sets the implicit flow configuration. + * + * @param implicit the implicit flow configuration + * @return this builder instance for method chaining + */ public Builder implicit(ImplicitOAuthFlow implicit) { this.implicit = implicit; return this; } + /** + * Sets the password flow configuration. + * + * @param password the password flow configuration + * @return this builder instance for method chaining + */ public Builder password(PasswordOAuthFlow password) { this.password = password; return this; } + /** + * Builds and returns a new OAuthFlows instance. + * + * @return a new OAuthFlows with the configured flow settings + */ public OAuthFlows build() { return new OAuthFlows(authorizationCode, clientCredentials, implicit, password); } diff --git a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java b/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java index f8f059792..cf115e32d 100644 --- a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java @@ -6,7 +6,24 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * Represents an OpenID Connect security scheme. + * Represents an OpenID Connect security scheme configuration for the A2A protocol. + * This record defines the OpenID Connect (OIDC) authentication mechanism that allows + * agents to authenticate users through an identity provider. + * + *

OpenID Connect is an identity layer built on top of OAuth 2.0 that enables + * clients to verify the identity of end-users based on authentication performed + * by an authorization server. It provides a standardized way to obtain basic + * profile information about the user.

+ * + *

Key components of this security scheme:

+ *
    + *
  • Type: Always "openIdConnect" to identify this as an OIDC scheme
  • + *
  • Description: Human-readable description of the authentication mechanism
  • + *
  • OpenID Connect URL: The discovery endpoint for the OIDC provider
  • + *
+ * + *

This implementation follows the OpenAPI Security Scheme Object specification + * for OpenID Connect, ensuring compatibility with standard OIDC implementations.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -45,20 +62,46 @@ public String getType() { return type; } + /** + * Builder class for constructing OpenIdConnectSecurityScheme instances. + * Provides a fluent API for configuring OpenID Connect security schemes. + */ public static class Builder { + /** The OpenID Connect discovery URL */ private String openIdConnectUrl; + + /** Description of the authentication mechanism */ private String description; + /** + * Sets the OpenID Connect discovery URL. + * This URL should point to the well-known configuration endpoint + * of the OpenID Connect provider (typically ending with /.well-known/openid_configuration). + * + * @param openIdConnectUrl the discovery URL for the OIDC provider + * @return this builder instance for method chaining + */ public Builder openIdConnectUrl(String openIdConnectUrl) { this.openIdConnectUrl = openIdConnectUrl; return this; } + /** + * Sets the human-readable description of the OpenID Connect authentication. + * + * @param description a description explaining how the authentication works + * @return this builder instance for method chaining + */ public Builder description(String description) { this.description = description; return this; } + /** + * Builds and returns a new OpenIdConnectSecurityScheme instance. + * + * @return a new OpenIdConnectSecurityScheme with the configured settings + */ public OpenIdConnectSecurityScheme build() { return new OpenIdConnectSecurityScheme(openIdConnectUrl, description); } diff --git a/spec/src/main/java/io/a2a/spec/Part.java b/spec/src/main/java/io/a2a/spec/Part.java index cf7f04a74..208b47e36 100644 --- a/spec/src/main/java/io/a2a/spec/Part.java +++ b/spec/src/main/java/io/a2a/spec/Part.java @@ -7,8 +7,11 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * A fundamental unit with a Message or Artifact. - * @param the type of unit + * Abstract base class for all content parts in the A2A protocol. + * A Part represents a unit of content that can be included in messages or artifacts. + * Different types of parts can contain text, files, data, tool calls, or other content types. + * + * @param the type of content this part contains */ @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, @@ -22,25 +25,52 @@ @JsonSubTypes.Type(value = DataPart.class, name = "data") }) public abstract class Part { + /** + * Enumeration of different part kinds/types supported in the A2A protocol. + */ public enum Kind { + /** Text content part */ TEXT("text"), + /** File content part */ FILE("file"), + /** Data content part */ DATA("data"); + /** The string representation of this kind */ private String kind; + /** + * Constructs a Kind with the specified string representation. + * + * @param kind the string representation of this kind + */ Kind(String kind) { this.kind = kind; } + /** + * Returns the string representation of this kind for JSON serialization. + * + * @return the string representation + */ @JsonValue public String asString() { return this.kind; } } + /** + * Returns the kind/type of this part. + * + * @return the part kind + */ public abstract Kind getKind(); + /** + * Returns the metadata associated with this part. + * + * @return the metadata map + */ public abstract Map getMetadata(); -} \ No newline at end of file +} diff --git a/spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java b/spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java index a42e74942..94803426e 100644 --- a/spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/PasswordOAuthFlow.java @@ -8,14 +8,103 @@ import io.a2a.util.Assert; /** - * Configuration for the OAuth Resource Owner Password flow. + * Represents the configuration for the OAuth 2.0 Resource Owner Password Credentials Grant flow. + * This record defines the settings required for the password flow, which allows clients + * to exchange a user's username and password directly for an access token. + * + *

Security Warning: The password flow is considered less secure than + * other OAuth 2.0 flows because it requires the client application to handle the user's + * credentials directly. It should only be used when:

+ *
    + *
  • The client is highly trusted (e.g., first-party applications)
  • + *
  • Other flows are not feasible
  • + *
  • The client and authorization server have a high degree of trust
  • + *
+ * + *

This flow is not recommended for new implementations and has been removed + * from OAuth 2.1. Consider using the Authorization Code flow with PKCE instead.

+ * + *

Required components:

+ *
    + *
  • Token URL: The endpoint where tokens are requested
  • + *
  • Refresh URL: Optional endpoint for refreshing tokens
  • + *
  • Scopes: Map of available scopes and their descriptions
  • + *
*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record PasswordOAuthFlow(String refreshUrl, Map scopes, String tokenUrl) { + /** + * Compact constructor for PasswordOAuthFlow. + * Validates that required parameters are not null. + * + * @throws IllegalArgumentException if scopes or tokenUrl is null + */ public PasswordOAuthFlow { Assert.checkNotNullParam("scopes", scopes); Assert.checkNotNullParam("tokenUrl", tokenUrl); } + + /** + * Builder class for constructing PasswordOAuthFlow instances. + * Provides a fluent API for configuring the OAuth password flow settings. + */ + public static class Builder { + /** The refresh endpoint URL */ + private String refreshUrl; + + /** Available OAuth scopes */ + private Map scopes; + + /** The token endpoint URL */ + private String tokenUrl; + + /** + * Sets the refresh endpoint URL. + * This is the optional URL where refresh tokens can be exchanged for new access tokens. + * + * @param refreshUrl the refresh endpoint URL (optional) + * @return this builder instance for method chaining + */ + public Builder refreshUrl(String refreshUrl) { + this.refreshUrl = refreshUrl; + return this; + } + + /** + * Sets the available OAuth scopes. + * Each scope defines a specific permission level, with the key being the scope name + * and the value being a human-readable description. + * + * @param scopes map of scope names to their descriptions + * @return this builder instance for method chaining + */ + public Builder scopes(Map scopes) { + this.scopes = scopes; + return this; + } + + /** + * Sets the token endpoint URL. + * This is the URL where the client will send username/password credentials + * to obtain an access token. + * + * @param tokenUrl the token endpoint URL (required) + * @return this builder instance for method chaining + */ + public Builder tokenUrl(String tokenUrl) { + this.tokenUrl = tokenUrl; + return this; + } + + /** + * Builds and returns a new PasswordOAuthFlow instance. + * + * @return a new PasswordOAuthFlow with the configured settings + */ + public PasswordOAuthFlow build() { + return new PasswordOAuthFlow(refreshUrl, scopes, tokenUrl); + } + } } diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationAuthenticationInfo.java b/spec/src/main/java/io/a2a/spec/PushNotificationAuthenticationInfo.java index b5b2bacd2..5c1a06d09 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationAuthenticationInfo.java +++ b/spec/src/main/java/io/a2a/spec/PushNotificationAuthenticationInfo.java @@ -7,13 +7,83 @@ import io.a2a.util.Assert; /** - * Defines authentication details for push notifications. + * Represents authentication information required for push notification delivery in the A2A protocol. + * This record contains the credentials and configuration needed to authenticate with + * push notification services and deliver notifications to client applications. + * + *

Push notifications in the A2A protocol allow agents to proactively notify clients + * about task updates, completion status, or other important events without requiring + * the client to continuously poll for updates.

+ * + *

The authentication information typically includes:

+ *
    + *
  • Service-specific credentials (API keys, tokens, certificates)
  • + *
  • Configuration parameters for the push notification provider
  • + *
  • Delivery preferences and routing information
  • + *
+ * + *

This implementation supports various push notification services and protocols, + * ensuring flexible integration with different client platforms and notification systems.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record PushNotificationAuthenticationInfo(List schemes, String credentials) { + /** + * Compact constructor that validates the input parameters. + * Ensures that the schemes parameter is not null as it's required + * for proper authentication configuration. + * + * @throws IllegalArgumentException if schemes is null + */ public PushNotificationAuthenticationInfo { Assert.checkNotNullParam("schemes", schemes); } + + /** + * Builder class for constructing PushNotificationAuthenticationInfo instances. + * Provides a fluent API for configuring push notification authentication. + */ + public static class Builder { + /** The authentication schemes supported for push notifications */ + private List schemes; + + /** The credentials for push notification authentication */ + private String credentials; + + /** + * Sets the authentication schemes supported for push notifications. + * These schemes define the authentication methods that can be used + * when delivering push notifications. + * + * @param schemes list of supported authentication scheme names + * @return this builder instance for method chaining + */ + public Builder schemes(List schemes) { + this.schemes = schemes; + return this; + } + + /** + * Sets the credentials for push notification authentication. + * These credentials are used to authenticate with the push notification + * service when delivering notifications to clients. + * + * @param credentials the authentication credentials + * @return this builder instance for method chaining + */ + public Builder credentials(String credentials) { + this.credentials = credentials; + return this; + } + + /** + * Builds and returns a new PushNotificationAuthenticationInfo instance. + * + * @return a new PushNotificationAuthenticationInfo with the configured settings + */ + public PushNotificationAuthenticationInfo build() { + return new PushNotificationAuthenticationInfo(schemes, credentials); + } + } } diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java index 34270637f..202a5bd07 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java +++ b/spec/src/main/java/io/a2a/spec/PushNotificationConfig.java @@ -5,7 +5,24 @@ import io.a2a.util.Assert; /** - * Represents a push notification. + * Represents the configuration for push notifications in the A2A protocol. + * This record defines the settings and parameters required to enable and configure + * push notification delivery for agent-to-application communication. + * + *

Push notifications provide a mechanism for agents to proactively notify client + * applications about important events, task updates, or status changes without + * requiring the client to continuously poll for updates. This improves efficiency + * and user experience by enabling real-time communication.

+ * + *

The configuration includes:

+ *
    + *
  • Authentication Information: Credentials and schemes for push services
  • + *
  • Delivery Settings: How and when notifications should be sent
  • + *
  • Service Configuration: Provider-specific settings and endpoints
  • + *
+ * + *

This implementation supports various push notification providers and protocols, + * allowing flexible integration with different client platforms and notification systems.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -15,10 +32,18 @@ public record PushNotificationConfig(String url, String token, PushNotificationA Assert.checkNotNullParam("url", url); } + /** + * Builder class for constructing PushNotificationConfig instances. + * Provides a fluent API for configuring push notification settings. + */ public static class Builder { + /** The URL endpoint for push notification delivery */ private String url; + /** The authentication token for push notification services */ private String token; + /** The authentication information for push notifications */ private PushNotificationAuthenticationInfo authentication; + /** Unique identifier for this push notification configuration */ private String id; public Builder() { @@ -30,27 +55,52 @@ public Builder(PushNotificationConfig notificationConfig) { this.authentication = notificationConfig.authentication; this.id = notificationConfig.id; } - + public Builder url(String url) { this.url = url; return this; } + /** + * Sets the authentication token for push notification services. + * + * @param token the authentication token + * @return this builder instance for method chaining + */ public Builder token(String token) { this.token = token; return this; } + /** + * Sets the authentication information for push notifications. + * This information is used to authenticate with push notification services + * when delivering notifications to client applications. + * + * @param authenticationInfo the authentication configuration for push notifications + * @return this builder instance for method chaining + */ public Builder authenticationInfo(PushNotificationAuthenticationInfo authenticationInfo) { this.authentication = authenticationInfo; return this; } + /** + * Sets the unique identifier for this push notification configuration. + * + * @param id the unique identifier + * @return this builder instance for method chaining + */ public Builder id(String id) { this.id = id; return this; } + /** + * Builds and returns a new PushNotificationConfig instance. + * + * @return a new PushNotificationConfig with the configured settings + */ public PushNotificationConfig build() { return new PushNotificationConfig(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 index d639b7bab..a2cd7c84f 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java @@ -7,10 +7,27 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * Represents a JSON-RPC error indicating that push notifications are not supported. + * This error is returned when a client attempts to configure or use push notification + * functionality on an agent that does not support this feature. + * + *

This error follows the JSON-RPC 2.0 error specification and uses a specific + * error code (-32003) to identify push notification support issues. It extends + * the base JSONRPCError class to provide structured error information.

+ * + *

Common scenarios where this error occurs:

+ *
    + *
  • Attempting to set task push notification configuration on an unsupported agent
  • + *
  • Trying to enable push notifications when the agent lacks the capability
  • + *
  • Requesting push notification features in environments where they're disabled
  • + *
+ */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class PushNotificationNotSupportedError extends JSONRPCError { + /** The default error code for push notification not supported errors */ public final static Integer DEFAULT_CODE = -32003; public PushNotificationNotSupportedError() { diff --git a/spec/src/main/java/io/a2a/spec/SecurityScheme.java b/spec/src/main/java/io/a2a/spec/SecurityScheme.java index 5003d01aa..4c596f876 100644 --- a/spec/src/main/java/io/a2a/spec/SecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/SecurityScheme.java @@ -5,6 +5,24 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +/** + * Sealed interface representing security schemes in the A2A protocol. + *

+ * This interface defines the contract for various authentication and authorization + * mechanisms that can be used to secure A2A agent communications. The interface + * uses Jackson annotations to support polymorphic JSON serialization and + * deserialization based on the "type" property. + *

+ *

+ * Supported security scheme types: + *

+ *
    + *
  • {@link APIKeySecurityScheme} - API key-based authentication
  • + *
  • {@link HTTPAuthSecurityScheme} - HTTP authentication (Basic, Bearer, etc.)
  • + *
  • {@link OAuth2SecurityScheme} - OAuth 2.0 authentication
  • + *
  • {@link OpenIdConnectSecurityScheme} - OpenID Connect authentication
  • + *
+ */ @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, @@ -19,5 +37,10 @@ }) public sealed interface SecurityScheme permits APIKeySecurityScheme, HTTPAuthSecurityScheme, OAuth2SecurityScheme, OpenIdConnectSecurityScheme { + /** + * Gets the description of this security scheme. + * + * @return a human-readable description of the security scheme + */ String getDescription(); } diff --git a/spec/src/main/java/io/a2a/spec/SendMessageRequest.java b/spec/src/main/java/io/a2a/spec/SendMessageRequest.java index d31f364e4..d5eac36b2 100644 --- a/spec/src/main/java/io/a2a/spec/SendMessageRequest.java +++ b/spec/src/main/java/io/a2a/spec/SendMessageRequest.java @@ -12,14 +12,45 @@ import io.a2a.util.Assert; /** - * Used to send a message request. + * Represents a JSON-RPC request for sending a message to an agent in the A2A protocol. + * This request is used to initiate message communication with an agent, allowing clients + * to send various types of messages including text, images, and other content. + * + *

The SendMessageRequest follows the JSON-RPC 2.0 specification and uses the + * "message/send" method. It encapsulates message parameters and configuration + * options for delivery and processing.

+ * + *

This is a non-streaming request, meaning it expects a single response + * rather than a stream of responses. For streaming message scenarios, + * use SendStreamingMessageRequest instead.

+ * + *

Example usage:

+ *
+ * MessageSendParams params = new MessageSendParams.Builder()
+ *     .message("Hello, agent!")
+ *     .build();
+ * SendMessageRequest request = new SendMessageRequest("request-123", params);
+ * 
*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class SendMessageRequest extends NonStreamingJSONRPCRequest { + /** The JSON-RPC method name for sending messages */ public static final String METHOD = "message/send"; + /** + * Creates a new SendMessageRequest with full parameter specification. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the request identifier (string, number, or null) + * @param method the JSON-RPC method name (must be "message/send") + * @param params the message parameters containing the message content and configuration + * @throws IllegalArgumentException if jsonrpc is null, empty, or not "2.0" + * @throws IllegalArgumentException if method is not "message/send" + * @throws IllegalArgumentException if params is null + * @throws IllegalArgumentException if id is not null, string, or integer + */ @JsonCreator public SendMessageRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("method") String method, @JsonProperty("params") MessageSendParams params) { @@ -41,36 +72,85 @@ public SendMessageRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty this.params = params; } + /** + * Creates a new SendMessageRequest with simplified parameters. + * Uses the default JSON-RPC version ("2.0") and method ("message/send"). + * + * @param id the request identifier (string, number, or null) + * @param params the message parameters containing the message content and configuration + */ public SendMessageRequest(Object id, MessageSendParams params) { this(JSONRPC_VERSION, id, METHOD, params); } + /** + * Builder class for constructing SendMessageRequest instances. + * Provides a fluent API for configuring request parameters. + */ public static class Builder { + /** The JSON-RPC protocol version */ private String jsonrpc; + + /** The request identifier */ private Object id; + + /** The JSON-RPC method name */ private String method; + + /** The message parameters */ private MessageSendParams params; + /** + * Sets the JSON-RPC protocol version. + * + * @param jsonrpc the JSON-RPC version (should be "2.0") + * @return this builder instance for method chaining + */ public Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } + /** + * Sets the request identifier. + * + * @param id the request identifier (string, number, or null) + * @return this builder instance for method chaining + */ public Builder id(Object id) { this.id = id; return this; } + /** + * Sets the JSON-RPC method name. + * + * @param method the method name (should be "message/send") + * @return this builder instance for method chaining + */ public Builder method(String method) { this.method = method; return this; } + /** + * Sets the message parameters. + * + * @param params the message parameters containing content and configuration + * @return this builder instance for method chaining + */ public Builder params(MessageSendParams params) { this.params = params; return this; } + /** + * Builds and returns a new SendMessageRequest instance. + * If no ID is specified, generates a random UUID as the request identifier. + * + * @return a new SendMessageRequest with the configured parameters + * @throws IllegalArgumentException if required parameters are invalid + */ public SendMessageRequest build() { if (id == null) { id = UUID.randomUUID().toString(); diff --git a/spec/src/main/java/io/a2a/spec/SendMessageResponse.java b/spec/src/main/java/io/a2a/spec/SendMessageResponse.java index 901beba90..319d4a0d2 100644 --- a/spec/src/main/java/io/a2a/spec/SendMessageResponse.java +++ b/spec/src/main/java/io/a2a/spec/SendMessageResponse.java @@ -9,22 +9,60 @@ import io.a2a.util.Assert; /** - * The response after receiving a send message request. + * Represents a JSON-RPC response for a message send request in the A2A protocol. + * This response is returned after an agent processes a SendMessageRequest, + * indicating the outcome of the message delivery attempt. + * + *

The response follows the JSON-RPC 2.0 specification and contains either + * a successful result (EventKind) or an error. The result indicates the type + * of event that was generated as a result of sending the message.

+ * + *

Possible outcomes:

+ *
    + *
  • Success: Contains an EventKind result indicating the message was processed
  • + *
  • Error: Contains a JSONRPCError describing what went wrong
  • + *
+ * + *

The EventKind result provides information about how the agent handled + * the message, such as whether it was accepted, queued, or processed immediately.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class SendMessageResponse extends JSONRPCResponse { + /** + * Creates a new SendMessageResponse with full parameter specification. + * + * @param jsonrpc the JSON-RPC protocol version (defaults to "2.0" if null) + * @param id the response identifier matching the original request ID + * @param result the successful result containing the event kind (null if error occurred) + * @param error the error information (null if successful) + * @throws IllegalArgumentException if id is not null, string, or integer + */ @JsonCreator public SendMessageResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("result") EventKind result, @JsonProperty("error") JSONRPCError error) { super(jsonrpc, id, result, error, EventKind.class); } + /** + * Creates a successful SendMessageResponse with the specified result. + * Uses the default JSON-RPC version ("2.0") and sets error to null. + * + * @param id the response identifier matching the original request ID + * @param result the successful result containing the event kind + */ public SendMessageResponse(Object id, EventKind result) { this(null, id, result, null); } + /** + * Creates an error SendMessageResponse with the specified error. + * Uses the default JSON-RPC version ("2.0") and sets result to null. + * + * @param id the response identifier matching the original request ID + * @param error the error information describing what went wrong + */ public SendMessageResponse(Object id, JSONRPCError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/SendStreamingMessageRequest.java b/spec/src/main/java/io/a2a/spec/SendStreamingMessageRequest.java index c4ebe8315..174fcea4f 100644 --- a/spec/src/main/java/io/a2a/spec/SendStreamingMessageRequest.java +++ b/spec/src/main/java/io/a2a/spec/SendStreamingMessageRequest.java @@ -11,14 +11,49 @@ import java.util.UUID; /** - * Used to initiate a task with streaming. + * Represents a JSON-RPC request for sending a streaming message to an agent in the A2A protocol. + * This request is used to initiate streaming message communication with an agent, allowing clients + * to send messages that expect a continuous stream of responses rather than a single response. + * + *

The SendStreamingMessageRequest follows the JSON-RPC 2.0 specification and uses the + * "message/stream" method. It encapsulates message parameters and configuration options + * for streaming delivery and processing.

+ * + *

Unlike SendMessageRequest which expects a single response, this streaming variant + * allows the agent to send multiple responses over time, making it suitable for: + *

    + *
  • Long-running tasks that provide progress updates
  • + *
  • Interactive conversations with real-time responses
  • + *
  • Tasks that generate incremental results
  • + *
+ * + *

Example usage:

+ *
+ * MessageSendParams params = new MessageSendParams.Builder()
+ *     .message("Generate a long report")
+ *     .build();
+ * SendStreamingMessageRequest request = new SendStreamingMessageRequest("stream-123", params);
+ * 
*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class SendStreamingMessageRequest extends StreamingJSONRPCRequest { + /** The JSON-RPC method name for streaming messages */ public static final String METHOD = "message/stream"; + /** + * Creates a new SendStreamingMessageRequest with full parameter specification. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the request identifier (string, number, or null) + * @param method the JSON-RPC method name (must be "message/stream") + * @param params the message parameters containing the message content and configuration + * @throws IllegalArgumentException if jsonrpc is not "2.0" + * @throws IllegalArgumentException if method is not "message/stream" + * @throws IllegalArgumentException if params is null + * @throws IllegalArgumentException if id is not null, string, or integer + */ @JsonCreator public SendStreamingMessageRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("method") String method, @JsonProperty("params") MessageSendParams params) { @@ -37,36 +72,85 @@ public SendStreamingMessageRequest(@JsonProperty("jsonrpc") String jsonrpc, @Jso this.params = params; } + /** + * Creates a new SendStreamingMessageRequest with simplified parameters. + * Uses the default JSON-RPC version ("2.0") and method ("message/stream"). + * + * @param id the request identifier (string, number, or null) + * @param params the message parameters containing the message content and configuration + */ public SendStreamingMessageRequest(Object id, MessageSendParams params) { this(null, id, METHOD, params); } + /** + * Builder class for constructing SendStreamingMessageRequest instances. + * Provides a fluent API for configuring streaming request parameters. + */ public static class Builder { + /** The JSON-RPC protocol version */ private String jsonrpc; + + /** The request identifier */ private Object id; + + /** The JSON-RPC method name (defaults to "message/stream") */ private String method = METHOD; + + /** The message parameters */ private MessageSendParams params; + /** + * Sets the JSON-RPC protocol version. + * + * @param jsonrpc the JSON-RPC version (should be "2.0") + * @return this builder instance for method chaining + */ public Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } + /** + * Sets the request identifier. + * + * @param id the request identifier (string, number, or null) + * @return this builder instance for method chaining + */ public Builder id(Object id) { this.id = id; return this; } + /** + * Sets the JSON-RPC method name. + * + * @param method the method name (should be "message/stream") + * @return this builder instance for method chaining + */ public Builder method(String method) { this.method = method; return this; } + /** + * Sets the message parameters. + * + * @param params the message parameters containing content and configuration + * @return this builder instance for method chaining + */ public Builder params(MessageSendParams params) { this.params = params; return this; } + /** + * Builds and returns a new SendStreamingMessageRequest instance. + * If no ID is specified, generates a random UUID as the request identifier. + * + * @return a new SendStreamingMessageRequest with the configured parameters + * @throws IllegalArgumentException if required parameters are invalid + */ public SendStreamingMessageRequest build() { if (id == null) { id = UUID.randomUUID().toString(); diff --git a/spec/src/main/java/io/a2a/spec/SendStreamingMessageResponse.java b/spec/src/main/java/io/a2a/spec/SendStreamingMessageResponse.java index f3bcb9676..dad66b927 100644 --- a/spec/src/main/java/io/a2a/spec/SendStreamingMessageResponse.java +++ b/spec/src/main/java/io/a2a/spec/SendStreamingMessageResponse.java @@ -9,22 +9,64 @@ import io.a2a.util.Assert; /** - * The response after receiving a request to initiate a task with streaming. + * Represents a JSON-RPC response for a streaming message request in the A2A protocol. + * This response is returned after an agent processes a SendStreamingMessageRequest, + * indicating the outcome of the streaming message initiation. + * + *

The response follows the JSON-RPC 2.0 specification and contains either + * a successful result (StreamingEventKind) or an error. The result indicates the type + * of streaming event that was generated as a result of initiating the streaming message.

+ * + *

Unlike SendMessageResponse which contains a single EventKind, this streaming variant + * contains a StreamingEventKind that represents the initial response to starting a + * streaming conversation. Subsequent streaming responses will be delivered separately.

+ * + *

Possible outcomes:

+ *
    + *
  • Success: Contains a StreamingEventKind result indicating streaming was initiated
  • + *
  • Error: Contains a JSONRPCError describing what went wrong during initiation
  • + *
+ * + *

The StreamingEventKind result provides information about how the agent handled + * the streaming request, such as whether it was accepted and streaming has begun.

*/ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class SendStreamingMessageResponse extends JSONRPCResponse { + /** + * Creates a new SendStreamingMessageResponse with full parameter specification. + * + * @param jsonrpc the JSON-RPC protocol version (defaults to "2.0" if null) + * @param id the response identifier matching the original request ID + * @param result the successful result containing the streaming event kind (null if error occurred) + * @param error the error information (null if successful) + * @throws IllegalArgumentException if id is not null, string, or integer + */ @JsonCreator public SendStreamingMessageResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("result") StreamingEventKind result, @JsonProperty("error") JSONRPCError error) { super(jsonrpc, id, result, error, StreamingEventKind.class); } + /** + * Creates a successful SendStreamingMessageResponse with the specified result. + * Uses the default JSON-RPC version ("2.0") and sets error to null. + * + * @param id the response identifier matching the original request ID + * @param result the successful result containing the streaming event kind + */ public SendStreamingMessageResponse(Object id, StreamingEventKind result) { this(null, id, result, null); } + /** + * Creates an error SendStreamingMessageResponse with the specified error. + * Uses the default JSON-RPC version ("2.0") and sets result to null. + * + * @param id the response identifier matching the original request ID + * @param error the error information describing what went wrong during streaming initiation + */ public SendStreamingMessageResponse(Object id, JSONRPCError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigRequest.java b/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigRequest.java index 7d53083a1..cfa50a693 100644 --- a/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigRequest.java +++ b/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigRequest.java @@ -12,14 +12,38 @@ import io.a2a.util.Assert; /** - * Used to set a task push notification request. + * Represents a JSON-RPC 2.0 request to configure push notification settings for a specific task. + * This request allows clients to set up push notification configurations that will be used + * to notify about task status changes, progress updates, or completion events. + * + *

Push notification configurations enable real-time communication between the agent + * and external systems, allowing for immediate notification delivery when task events occur. + * This is particularly useful for long-running tasks where clients need to be notified + * of progress or completion without polling.

+ * + *

The request follows the JSON-RPC 2.0 specification and uses the method + * "tasks/pushNotificationConfig/set" to identify this operation type.

+ * + * @see TaskPushNotificationConfig + * @see NonStreamingJSONRPCRequest */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class SetTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { + /** The JSON-RPC method name for setting task push notification configuration */ public static final String METHOD = "tasks/pushNotificationConfig/set"; + /** + * Creates a new SetTaskPushNotificationConfigRequest with all JSON-RPC 2.0 fields. + * This constructor is primarily used by JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the request identifier (string, number, or null) + * @param method the method name (must be "tasks/pushNotificationConfig/set") + * @param params the task push notification configuration parameters + * @throws IllegalArgumentException if jsonrpc version is invalid, method is incorrect, or params is null + */ @JsonCreator public SetTaskPushNotificationConfigRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("method") String method, @JsonProperty("params") TaskPushNotificationConfig params) { @@ -38,36 +62,84 @@ public SetTaskPushNotificationConfigRequest(@JsonProperty("jsonrpc") String json this.params = params; } + /** + * Creates a new SetTaskPushNotificationConfigRequest with simplified parameters. + * The JSON-RPC version defaults to "2.0" and the method is automatically set. + * + * @param id the request identifier + * @param taskPushConfig the task push notification configuration + */ public SetTaskPushNotificationConfigRequest(String id, TaskPushNotificationConfig taskPushConfig) { this(null, id, METHOD, taskPushConfig); } + /** + * Builder class for constructing SetTaskPushNotificationConfigRequest instances. + * Provides a fluent API for setting request parameters with validation. + */ public static class Builder { + /** The JSON-RPC protocol version */ private String jsonrpc; + + /** The request identifier */ private Object id; + + /** The JSON-RPC method name */ private String method = METHOD; + + /** The task push notification configuration parameters */ private TaskPushNotificationConfig params; + /** + * Sets the JSON-RPC protocol version. + * + * @param jsonrpc the JSON-RPC version (should be "2.0") + * @return this builder instance for method chaining + */ public SetTaskPushNotificationConfigRequest.Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } + /** + * Sets the request identifier. + * + * @param id the request identifier (string, number, or null) + * @return this builder instance for method chaining + */ public SetTaskPushNotificationConfigRequest.Builder id(Object id) { this.id = id; return this; } + /** + * Sets the JSON-RPC method name. + * + * @param method the method name (should be "tasks/pushNotificationConfig/set") + * @return this builder instance for method chaining + */ public SetTaskPushNotificationConfigRequest.Builder method(String method) { this.method = method; return this; } + /** + * Sets the task push notification configuration parameters. + * + * @param params the task push notification configuration + * @return this builder instance for method chaining + */ public SetTaskPushNotificationConfigRequest.Builder params(TaskPushNotificationConfig params) { this.params = params; return this; } + /** + * Builds and returns a new SetTaskPushNotificationConfigRequest instance. + * If no ID is provided, a random UUID will be generated. + * + * @return a new SetTaskPushNotificationConfigRequest with the configured parameters + */ public SetTaskPushNotificationConfigRequest build() { if (id == null) { id = UUID.randomUUID().toString(); diff --git a/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigResponse.java b/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigResponse.java index c40f18f18..0fc3a304f 100644 --- a/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigResponse.java +++ b/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigResponse.java @@ -6,12 +6,36 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * The response after receiving a set task push notification request. + * Represents a JSON-RPC 2.0 response to a task push notification configuration request. + * This response is sent back to the client after processing a SetTaskPushNotificationConfigRequest, + * indicating whether the push notification configuration was successfully set or if an error occurred. + * + *

The response can contain either:

+ *
    + *
  • A successful result with the configured TaskPushNotificationConfig
  • + *
  • An error object describing what went wrong during the configuration process
  • + *
+ * + *

This follows the JSON-RPC 2.0 specification for response messages, ensuring + * compatibility with standard JSON-RPC clients and tooling.

+ * + * @see SetTaskPushNotificationConfigRequest + * @see TaskPushNotificationConfig + * @see JSONRPCResponse */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class SetTaskPushNotificationConfigResponse extends JSONRPCResponse { + /** + * Creates a new SetTaskPushNotificationConfigResponse with all JSON-RPC 2.0 fields. + * This constructor is primarily used by JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (should be "2.0") + * @param id the request identifier that matches the original request + * @param result the task push notification configuration result (null if error occurred) + * @param error the error object (null if successful) + */ @JsonCreator public SetTaskPushNotificationConfigResponse(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("result") TaskPushNotificationConfig result, @@ -19,10 +43,24 @@ public SetTaskPushNotificationConfigResponse(@JsonProperty("jsonrpc") String jso super(jsonrpc, id, result, error, TaskPushNotificationConfig.class); } + /** + * Creates an error response for a task push notification configuration request. + * The JSON-RPC version defaults to "2.0" and the result is set to null. + * + * @param id the request identifier that matches the original request + * @param error the error object describing what went wrong + */ public SetTaskPushNotificationConfigResponse(Object id, JSONRPCError error) { this(null, id, null, error); } + /** + * Creates a successful response for a task push notification configuration request. + * The JSON-RPC version defaults to "2.0" and the error is set to null. + * + * @param id the request identifier that matches the original request + * @param result the successfully configured task push notification configuration + */ public SetTaskPushNotificationConfigResponse(Object id, TaskPushNotificationConfig result) { this(null, id, result, null); } diff --git a/spec/src/main/java/io/a2a/spec/StreamingEventKind.java b/spec/src/main/java/io/a2a/spec/StreamingEventKind.java index a7a6b6232..877347c90 100644 --- a/spec/src/main/java/io/a2a/spec/StreamingEventKind.java +++ b/spec/src/main/java/io/a2a/spec/StreamingEventKind.java @@ -8,6 +8,28 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +/** + * Sealed interface for events that can be streamed in the A2A protocol. + * + * This interface extends {@link Event} and provides polymorphic JSON serialization/deserialization + * support for streaming events in the A2A framework. The "kind" property is used as a discriminator + * to determine the concrete type during JSON processing in streaming contexts. + * + * Currently supported streaming event kinds include: + *
    + *
  • {@code "task"} - Represents a {@link Task} object
  • + *
  • {@code "message"} - Represents a {@link Message} object
  • + *
  • {@code "status-update"} - Represents a {@link TaskStatusUpdateEvent}
  • + *
  • {@code "artifact-update"} - Represents a {@link TaskArtifactUpdateEvent}
  • + *
+ * + * The sealed interface restricts implementations to the explicitly permitted classes, + * ensuring type safety and enabling exhaustive pattern matching in switch expressions. + * + * The Jackson annotations configure automatic type resolution based on the "kind" field + * in JSON data, enabling seamless conversion between JSON and the appropriate Java types + * during streaming operations. + */ @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, @@ -22,5 +44,14 @@ }) public sealed interface StreamingEventKind extends Event permits Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent { + /** + * Returns the kind/type identifier for this streaming event. + * + * This method provides the discriminator value used for JSON serialization + * and type resolution in streaming contexts. The returned string should match + * one of the values defined in the {@link JsonSubTypes} annotation. + * + * @return the kind identifier (e.g., "task", "message", "status-update", "artifact-update") + */ String getKind(); } diff --git a/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequest.java b/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequest.java index 7642c41d2..66a3eff03 100644 --- a/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequest.java +++ b/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequest.java @@ -5,7 +5,30 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize; /** - * Represents a streaming JSON-RPC request. + * Abstract base class for streaming JSON-RPC 2.0 requests in the A2A protocol. + * Streaming requests are designed to handle operations that may produce continuous + * or real-time data streams, such as task resubscription or streaming message sending. + * + *

This class extends the base JSONRPCRequest and provides specialized handling + * for streaming operations. Streaming requests typically involve:

+ *
    + *
  • Long-running operations that produce incremental results
  • + *
  • Real-time data transmission
  • + *
  • Continuous monitoring or subscription-based operations
  • + *
+ * + *

The class is sealed and only permits specific implementations: + * TaskResubscriptionRequest and SendStreamingMessageRequest, ensuring type safety + * and controlled extensibility.

+ * + *

Deserialization is handled by the StreamingJSONRPCRequestDeserializer to + * properly route incoming JSON to the correct concrete implementation.

+ * + * @param the type of the request parameters + * @see JSONRPCRequest + * @see TaskResubscriptionRequest + * @see SendStreamingMessageRequest + * @see StreamingJSONRPCRequestDeserializer */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequestDeserializer.java b/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequestDeserializer.java index 236ad547a..bb752b996 100644 --- a/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequestDeserializer.java +++ b/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequestDeserializer.java @@ -7,16 +7,56 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; +/** + * Custom Jackson deserializer for streaming JSON-RPC 2.0 requests in the A2A protocol. + * This deserializer examines the "method" field of incoming JSON to determine which + * specific StreamingJSONRPCRequest subclass should be instantiated. + * + *

The deserializer supports the following streaming request types:

+ *
    + *
  • TaskResubscriptionRequest - for resubscribing to task updates
  • + *
  • SendStreamingMessageRequest - for sending streaming messages
  • + *
+ * + *

The deserialization process validates the JSON-RPC structure, extracts the method name, + * and routes to the appropriate concrete class constructor. If an unsupported method is + * encountered, a MethodNotFoundJsonMappingException is thrown.

+ * + * @param the generic type parameter (not used in this implementation) + * @see StreamingJSONRPCRequest + * @see JSONRPCRequestDeserializerBase + * @see TaskResubscriptionRequest + * @see SendStreamingMessageRequest + */ public class StreamingJSONRPCRequestDeserializer extends JSONRPCRequestDeserializerBase> { + /** + * Default constructor for the streaming JSON-RPC request deserializer. + */ public StreamingJSONRPCRequestDeserializer() { this(null); } + /** + * Constructor with value class parameter. + * + * @param vc the value class (typically not used) + */ public StreamingJSONRPCRequestDeserializer(Class vc) { super(vc); } + /** + * Deserializes JSON into the appropriate StreamingJSONRPCRequest subclass. + * The method field is used to determine which specific request type to create. + * + * @param jsonParser the JSON parser containing the request data + * @param context the deserialization context + * @return the appropriate StreamingJSONRPCRequest subclass instance + * @throws IOException if JSON parsing fails + * @throws JsonProcessingException if JSON processing fails + * @throws MethodNotFoundJsonMappingException if the method is not supported + */ @Override public StreamingJSONRPCRequest deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { diff --git a/spec/src/main/java/io/a2a/spec/StringJsonrpcId.java b/spec/src/main/java/io/a2a/spec/StringJsonrpcId.java index 74a28272f..65cad17af 100644 --- a/spec/src/main/java/io/a2a/spec/StringJsonrpcId.java +++ b/spec/src/main/java/io/a2a/spec/StringJsonrpcId.java @@ -1,4 +1,24 @@ package io.a2a.spec; +/** + * Utility class for handling string-based JSON-RPC request identifiers. + * This class provides functionality for working with string IDs in JSON-RPC 2.0 requests + * and responses within the A2A protocol. + * + *

JSON-RPC 2.0 allows request identifiers to be strings, numbers, or null. + * This class specifically handles the string variant, which is commonly used + * for human-readable or UUID-based request tracking.

+ * + *

String IDs are particularly useful for:

+ *
    + *
  • Debugging and logging purposes
  • + *
  • Correlation with external systems
  • + *
  • UUID-based request tracking
  • + *
  • Human-readable request identification
  • + *
+ * + * @see JSONRPCRequest + * @see JSONRPCResponse + */ public class StringJsonrpcId { } diff --git a/spec/src/main/java/io/a2a/spec/Task.java b/spec/src/main/java/io/a2a/spec/Task.java index 86c92473e..bb29894c8 100644 --- a/spec/src/main/java/io/a2a/spec/Task.java +++ b/spec/src/main/java/io/a2a/spec/Task.java @@ -11,7 +11,9 @@ import io.a2a.util.Assert; /** - * A central unit of work. + * Represents a task in the A2A protocol. + * A task encapsulates a unit of work with its current state, artifacts, message history, and metadata. + * Tasks are the primary way to track and manage work progress in agent-to-agent communication. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) @@ -20,19 +22,72 @@ public final class Task implements EventKind, StreamingEventKind { public static final TypeReference TYPE_REFERENCE = new TypeReference<>() {}; public static final String TASK = "task"; + + /** + * Unique identifier for this task. + */ private final String id; + + /** + * Identifier for the conversation context this task belongs to. + */ private final String contextId; + + /** + * Current status of the task (e.g., pending, in_progress, completed, failed). + */ private final TaskStatus status; + + /** + * List of artifacts produced or associated with this task. + * Artifacts represent the outputs or deliverables of the task. + */ private final List artifacts; + + /** + * Message history associated with this task. + * Contains all messages that are part of this task's execution. + */ private final List history; + + /** + * Additional metadata associated with this task. + * Can contain custom properties specific to the implementation or task type. + */ private final Map metadata; + + /** + * The kind/type of this object, always "task" for Task instances. + */ private final String kind; + /** + * Constructs a new Task with the specified properties. + * The kind is automatically set to "task". + * + * @param id unique identifier for this task + * @param contextId identifier for the conversation context + * @param status current status of the task + * @param artifacts list of artifacts associated with this task + * @param history message history for this task + * @param metadata additional metadata for this task + */ public Task(String id, String contextId, TaskStatus status, List artifacts, List history, Map metadata) { this(id, contextId, status, artifacts, history, metadata, TASK); } + /** + * Constructs a new Task with the specified properties and kind. + * + * @param id unique identifier for this task + * @param contextId identifier for the conversation context + * @param status current status of the task + * @param artifacts list of artifacts associated with this task + * @param history message history for this task + * @param metadata additional metadata for this task + * @param kind the kind/type of this object, must be "task" + */ @JsonCreator public Task(@JsonProperty("id") String id, @JsonProperty("contextId") String contextId, @JsonProperty("status") TaskStatus status, @JsonProperty("artifacts") List artifacts, @JsonProperty("history") List history, @@ -53,30 +108,65 @@ public Task(@JsonProperty("id") String id, @JsonProperty("contextId") String con this.kind = kind; } + /** + * Returns the unique identifier for this task. + * + * @return the task ID + */ public String getId() { return id; } + /** + * Returns the identifier for the conversation context this task belongs to. + * + * @return the context ID + */ public String getContextId() { return contextId; } + /** + * Returns the current status of the task. + * + * @return the task status + */ public TaskStatus getStatus() { return status; } + /** + * Returns the list of artifacts associated with this task. + * + * @return the artifacts list + */ public List getArtifacts() { return artifacts; } + /** + * Returns the message history for this task. + * + * @return the message history + */ public List getHistory() { return history; } + /** + * Returns the additional metadata associated with this task. + * + * @return the metadata map + */ public Map getMetadata() { return metadata; } + /** + * Returns the kind/type of this object. + * + * @return the kind string, always "task" for Task instances + */ public String getKind() { return kind; } @@ -89,10 +179,18 @@ public static class Builder { private List history; private Map metadata; + /** + * Creates a new empty Builder. + */ public Builder() { } + /** + * Creates a new Builder initialized with values from an existing Task. + * + * @param task the task to copy values from + */ public Builder(Task task) { id = task.id; contextId = task.contextId; @@ -103,41 +201,88 @@ public Builder(Task task) { } + /** + * Sets the task ID. + * + * @param id the task ID + * @return this builder + */ public Builder id(String id) { this.id = id; return this; } + /** + * Sets the context ID. + * + * @param contextId the context ID + * @return this builder + */ public Builder contextId(String contextId) { this.contextId = contextId; return this; } + /** + * Sets the task status. + * + * @param status the task status + * @return this builder + */ public Builder status(TaskStatus status) { this.status = status; return this; } + /** + * Sets the artifacts list. + * + * @param artifacts the artifacts list + * @return this builder + */ public Builder artifacts(List artifacts) { this.artifacts = artifacts; return this; } + /** + * Sets the message history. + * + * @param history the message history + * @return this builder + */ public Builder history(List history) { this.history = history; return this; } + /** + * Sets the message history from varargs. + * + * @param history the messages + * @return this builder + */ public Builder history(Message... history) { this.history = List.of(history); return this; } + /** + * Sets the metadata. + * + * @param metadata the metadata map + * @return this builder + */ public Builder metadata(Map metadata) { this.metadata = metadata; return this; } + /** + * Builds a new Task instance with the configured properties. + * + * @return a new Task instance + */ public Task build() { return new Task(id, contextId, 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 index 49485577b..0a1b4773a 100644 --- a/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java +++ b/spec/src/main/java/io/a2a/spec/TaskArtifactUpdateEvent.java @@ -9,25 +9,85 @@ import io.a2a.util.Assert; /** - * A task artifact update event. + * Represents a task artifact update event in the A2A protocol. + * + * This event is emitted when a task produces or updates an artifact during execution, + * providing real-time notifications about artifact creation, modification, or completion. + * It implements both {@link EventKind} and {@link StreamingEventKind} to support + * different event processing patterns in the A2A framework. + * + * The event contains information about which task produced the artifact, the artifact + * itself, the context it belongs to, whether this is an append operation, whether this + * is the last chunk of a streaming artifact, and any additional metadata. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class TaskArtifactUpdateEvent implements EventKind, StreamingEventKind { public static final String ARTIFACT_UPDATE = "artifact-update"; + /** + * The unique identifier of the task that produced or updated the artifact. + */ private final String taskId; + + /** + * Indicates whether this artifact update should be appended to existing content. + * If true, the artifact content should be appended; if false or null, it should replace existing content. + */ private final Boolean append; + + /** + * Indicates whether this is the last chunk of a streaming artifact. + * Used for streaming scenarios where artifacts are sent in multiple chunks. + */ private final Boolean lastChunk; + + /** + * The artifact that was produced or updated by the task. + */ private final Artifact artifact; + + /** + * The identifier of the context/conversation this task belongs to. + */ private final String contextId; + + /** + * Additional metadata associated with this artifact update. + * Can contain implementation-specific information about the artifact update. + */ private final Map metadata; + + /** + * The kind/type of this event, always "artifact-update" for TaskArtifactUpdateEvent instances. + */ private final String kind; + /** + * Constructs a new TaskArtifactUpdateEvent with the specified properties. + * + * @param taskId the unique identifier of the task that produced the artifact + * @param artifact the artifact that was produced or updated + * @param contextId the identifier of the context/conversation this task belongs to + * @param append whether this artifact update should be appended to existing content + * @param lastChunk whether this is the last chunk of a streaming artifact + * @param metadata additional metadata associated with this artifact update + */ public TaskArtifactUpdateEvent(String taskId, Artifact artifact, String contextId, Boolean append, Boolean lastChunk, Map metadata) { this(taskId, artifact, contextId, append, lastChunk, metadata, ARTIFACT_UPDATE); } + /** + * JSON constructor for creating TaskArtifactUpdateEvent instances from JSON data. + * + * @param taskId the unique identifier of the task that produced the artifact + * @param artifact the artifact that was produced or updated + * @param contextId the identifier of the context/conversation this task belongs to + * @param append whether this artifact update should be appended to existing content + * @param lastChunk whether this is the last chunk of a streaming artifact + * @param metadata additional metadata associated with this artifact update + * @param kind the kind/type of this event + */ @JsonCreator public TaskArtifactUpdateEvent(@JsonProperty("taskId") String taskId, @JsonProperty("artifact") Artifact artifact, @JsonProperty("contextId") String contextId, @@ -51,35 +111,73 @@ public TaskArtifactUpdateEvent(@JsonProperty("taskId") String taskId, @JsonPrope this.kind = kind; } + /** + * Gets the unique identifier of the task that produced or updated the artifact. + * + * @return the task ID + */ public String getTaskId() { return taskId; } + /** + * Gets the artifact that was produced or updated by the task. + * + * @return the artifact + */ public Artifact getArtifact() { return artifact; } + /** + * Gets the identifier of the context/conversation this task belongs to. + * + * @return the context ID + */ public String getContextId() { return contextId; } + /** + * Indicates whether this artifact update should be appended to existing content. + * + * @return true if content should be appended, false if it should replace, null if not specified + */ public Boolean isAppend() { return append; } + /** + * Indicates whether this is the last chunk of a streaming artifact. + * + * @return true if this is the last chunk, false if more chunks are expected, null if not applicable + */ public Boolean isLastChunk() { return lastChunk; } + /** + * Gets the additional metadata associated with this artifact update. + * + * @return the metadata map + */ public Map getMetadata() { return metadata; } + /** + * Gets the kind/type of this event. + * + * @return the event kind, always "artifact-update" for TaskArtifactUpdateEvent instances + */ @Override public String getKind() { return kind; } + /** + * Builder class for constructing {@link TaskArtifactUpdateEvent} instances. + */ public static class Builder { private String taskId; @@ -89,37 +187,77 @@ public static class Builder { private Boolean lastChunk; private Map metadata; + /** + * Sets the unique identifier of the task that produced or updated the artifact. + * + * @param taskId the task ID + * @return this builder instance + */ public Builder taskId(String taskId) { this.taskId = taskId; return this; } + /** + * Sets the artifact that was produced or updated by the task. + * + * @param artifact the artifact + * @return this builder instance + */ public Builder artifact(Artifact artifact) { this.artifact = artifact; return this; } + /** + * Sets the identifier of the context/conversation this task belongs to. + * + * @param contextId the context ID + * @return this builder instance + */ public Builder contextId(String contextId) { this.contextId = contextId; return this; } + /** + * Sets whether this artifact update should be appended to existing content. + * + * @param append true if content should be appended, false if it should replace, null if not specified + * @return this builder instance + */ public Builder append(Boolean append) { this.append = append; return this; } + /** + * Sets whether this is the last chunk of a streaming artifact. + * + * @param lastChunk true if this is the last chunk, false if more chunks are expected, null if not applicable + * @return this builder instance + */ public Builder lastChunk(Boolean lastChunk) { this.lastChunk = lastChunk; return this; } - + /** + * Sets the additional metadata associated with this artifact update. + * + * @param metadata the metadata map + * @return this builder instance + */ public Builder metadata(Map metadata) { this.metadata = metadata; return this; } + /** + * Builds and returns a new {@link TaskArtifactUpdateEvent} instance with the configured properties. + * + * @return a new TaskArtifactUpdateEvent instance + */ public TaskArtifactUpdateEvent build() { return new TaskArtifactUpdateEvent(taskId, artifact, 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 index 816550eb9..41bb4270b 100644 --- a/spec/src/main/java/io/a2a/spec/TaskIdParams.java +++ b/spec/src/main/java/io/a2a/spec/TaskIdParams.java @@ -7,16 +7,39 @@ import io.a2a.util.Assert; /** - * Task id parameters. + * Represents task identifier parameters in the A2A protocol. + *

+ * This record encapsulates a task ID along with optional metadata. + * It is commonly used in API requests and responses that need to + * reference a specific task, such as task queries, updates, or + * status requests. + *

+ * + * @param id the unique identifier of the task + * @param metadata optional metadata associated with the task identifier */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record TaskIdParams(String id, Map metadata) { + /** + * Compact constructor that validates the task ID parameters. + *

+ * This constructor ensures that the task ID is not null, as it is + * required to uniquely identify the task. + *

+ * + * @throws IllegalArgumentException if id is null + */ public TaskIdParams { Assert.checkNotNullParam("id", id); } + /** + * Convenience constructor for creating TaskIdParams with only an ID. + * + * @param id the unique identifier of the task + */ public TaskIdParams(String id) { this(id, null); } diff --git a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java index aa40a81d3..ceedd1d38 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java @@ -7,16 +7,49 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * Represents a JSON-RPC 2.0 error indicating that a task cannot be canceled. + * This error is returned when a client attempts to cancel a task that is not + * in a cancelable state, such as tasks that have already completed, failed, + * or are in a critical phase where cancellation is not permitted. + * + *

Common scenarios where this error occurs:

+ *
    + *
  • Task has already completed successfully
  • + *
  • Task has already failed or been canceled
  • + *
  • Task is in a critical execution phase where cancellation would cause data corruption
  • + *
  • Task type does not support cancellation by design
  • + *
+ * + *

The error follows JSON-RPC 2.0 error object specification with a default + * error code of -32002 and a descriptive message. Additional context can be + * provided through the data field.

+ * + * @see JSONRPCError + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class TaskNotCancelableError extends JSONRPCError { + /** Default error code for task not cancelable errors */ public final static Integer DEFAULT_CODE = -32002; + /** + * Creates a TaskNotCancelableError with default values. + * Uses the default error code and message. + */ public TaskNotCancelableError() { this(null, null, null); } + /** + * Creates a TaskNotCancelableError with custom values. + * Any null parameters will be replaced with default values. + * + * @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 (can be null) + */ @JsonCreator public TaskNotCancelableError( @JsonProperty("code") Integer code, diff --git a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java index 26ee264e3..743b8e201 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java @@ -7,18 +7,49 @@ import static io.a2a.util.Utils.defaultIfNull; +/** + * Represents a JSON-RPC 2.0 error indicating that a requested task was not found. + * This error is returned when a client attempts to access, modify, or query a task + * that does not exist in the agent's task registry or has been removed. + * + *

Common scenarios where this error occurs:

+ *
    + *
  • Task ID does not exist in the system
  • + *
  • Task has been deleted or expired
  • + *
  • Task ID format is invalid or malformed
  • + *
  • Client lacks permission to access the specified task
  • + *
+ * + *

The error follows JSON-RPC 2.0 error object specification with a default + * error code of -32001 and a descriptive message. Additional context such as + * the invalid task ID can be provided through the data field.

+ * + * @see JSONRPCError + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class TaskNotFoundError extends JSONRPCError { + /** Default error code for task not found errors */ public final static Integer DEFAULT_CODE = -32001; + /** + * Creates a TaskNotFoundError with default values. + * Uses the default error code and message. + */ public TaskNotFoundError() { this(null, null, null); } + /** + * Creates a TaskNotFoundError with custom values. + * Any null parameters will be replaced with default values. + * + * @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, such as the invalid task ID (can be null) + */ @JsonCreator - public TaskNotFoundError( @JsonProperty("code") Integer code, @JsonProperty("message") String message, diff --git a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java index 0e4163212..5b358ec1f 100644 --- a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java +++ b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java @@ -5,12 +5,37 @@ import io.a2a.util.Assert; /** - * Task push notification configuration. + * Represents the configuration for push notifications associated with a specific task. + * This record binds a task identifier to its corresponding push notification settings, + * enabling the agent to send real-time notifications about task status changes, + * progress updates, or completion events. + * + *

Task push notification configurations are essential for:

+ *
    + *
  • Real-time task status monitoring
  • + *
  • Progress tracking for long-running operations
  • + *
  • Immediate notification of task completion or failure
  • + *
  • Integration with external monitoring and alerting systems
  • + *
+ * + *

The configuration ensures that clients can receive timely updates about + * task execution without the need for continuous polling, improving efficiency + * and user experience.

+ * + * @param taskId the unique identifier of the task to monitor + * @param pushNotificationConfig the push notification configuration settings + * @see PushNotificationConfig */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record TaskPushNotificationConfig(String taskId, PushNotificationConfig pushNotificationConfig) { + /** + * Compact constructor that validates the required parameters. + * Ensures that both taskId and pushNotificationConfig are not null. + * + * @throws IllegalArgumentException if taskId or pushNotificationConfig is null + */ public TaskPushNotificationConfig { Assert.checkNotNullParam("taskId", taskId); Assert.checkNotNullParam("pushNotificationConfig", pushNotificationConfig); diff --git a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java b/spec/src/main/java/io/a2a/spec/TaskQueryParams.java index 2587e5fb5..895e097f0 100644 --- a/spec/src/main/java/io/a2a/spec/TaskQueryParams.java +++ b/spec/src/main/java/io/a2a/spec/TaskQueryParams.java @@ -7,16 +7,30 @@ import io.a2a.util.Assert; /** - * Task query parameters. + * Represents parameters for querying task information in the A2A protocol. + *

+ * This record encapsulates the parameters needed to query a specific task, + * including options to control the amount of historical data returned and + * additional metadata for the query. + *

* - * @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 metadata additional properties + * @param id the unique identifier of the task to be queried + * @param historyLength the maximum number of historical items to include in the response (null for default) + * @param metadata additional properties and metadata for the query */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record TaskQueryParams(String id, Integer historyLength, Map metadata) { + /** + * Compact constructor that validates the task query parameters. + *

+ * This constructor ensures that the task ID is not null and that + * the history length, if specified, is not negative. + *

+ * + * @throws IllegalArgumentException if id is null or historyLength is negative + */ public TaskQueryParams { Assert.checkNotNullParam("id", id); if (historyLength != null && historyLength < 0) { @@ -24,10 +38,21 @@ public record TaskQueryParams(String id, Integer historyLength, MapTask resubscription is typically used in scenarios such as:

+ *
    + *
  • Reconnecting after a network disconnection
  • + *
  • Resuming monitoring of long-running tasks
  • + *
  • Re-establishing event streams after client restart
  • + *
  • Switching between different monitoring configurations
  • + *
+ * + *

As a streaming request, this operation establishes a persistent connection + * that delivers continuous updates until the task completes or the subscription + * is explicitly canceled. The request follows the JSON-RPC 2.0 specification + * and uses the method "tasks/resubscribe".

+ * + * @see StreamingJSONRPCRequest + * @see TaskIdParams */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class TaskResubscriptionRequest extends StreamingJSONRPCRequest { + /** The JSON-RPC method name for task resubscription requests */ public static final String METHOD = "tasks/resubscribe"; + /** + * Creates a new TaskResubscriptionRequest with all JSON-RPC 2.0 fields. + * This constructor is primarily used by JSON deserialization. + * + * @param jsonrpc the JSON-RPC protocol version (must be "2.0") + * @param id the request identifier (string, number, or null; auto-generated if null) + * @param method the method name (must be "tasks/resubscribe") + * @param params the task ID parameters specifying which task to resubscribe to + * @throws IllegalArgumentException if jsonrpc version is invalid, method is incorrect, or params is null + */ @JsonCreator public TaskResubscriptionRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonProperty("id") Object id, @JsonProperty("method") String method, @JsonProperty("params") TaskIdParams params) { @@ -36,36 +65,84 @@ public TaskResubscriptionRequest(@JsonProperty("jsonrpc") String jsonrpc, @JsonP this.params = params; } + /** + * Creates a new TaskResubscriptionRequest with simplified parameters. + * The JSON-RPC version defaults to "2.0" and the method is automatically set. + * + * @param id the request identifier + * @param params the task ID parameters specifying which task to resubscribe to + */ public TaskResubscriptionRequest(Object id, TaskIdParams params) { this(null, id, METHOD, params); } + /** + * Builder class for constructing TaskResubscriptionRequest instances. + * Provides a fluent API for setting request parameters with validation. + */ public static class Builder { + /** The JSON-RPC protocol version */ private String jsonrpc; + + /** The request identifier */ private Object id; + + /** The JSON-RPC method name */ private String method = METHOD; + + /** The task ID parameters */ private TaskIdParams params; + /** + * Sets the JSON-RPC protocol version. + * + * @param jsonrpc the JSON-RPC version (should be "2.0") + * @return this builder instance for method chaining + */ public TaskResubscriptionRequest.Builder jsonrpc(String jsonrpc) { this.jsonrpc = jsonrpc; return this; } + /** + * Sets the request identifier. + * + * @param id the request identifier (string, number, or null) + * @return this builder instance for method chaining + */ public TaskResubscriptionRequest.Builder id(Object id) { this.id = id; return this; } + /** + * Sets the JSON-RPC method name. + * + * @param method the method name (should be "tasks/resubscribe") + * @return this builder instance for method chaining + */ public TaskResubscriptionRequest.Builder method(String method) { this.method = method; return this; } + /** + * Sets the task ID parameters. + * + * @param params the task ID parameters specifying which task to resubscribe to + * @return this builder instance for method chaining + */ public TaskResubscriptionRequest.Builder params(TaskIdParams params) { this.params = params; return this; } + /** + * Builds and returns a new TaskResubscriptionRequest instance. + * If no ID is provided, a random UUID will be generated. + * + * @return a new TaskResubscriptionRequest with the configured parameters + */ public TaskResubscriptionRequest build() { if (id == null) { id = UUID.randomUUID().toString(); diff --git a/spec/src/main/java/io/a2a/spec/TaskState.java b/spec/src/main/java/io/a2a/spec/TaskState.java index 30d3c1a23..f4171d98c 100644 --- a/spec/src/main/java/io/a2a/spec/TaskState.java +++ b/spec/src/main/java/io/a2a/spec/TaskState.java @@ -4,40 +4,92 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * Represents the state of a task. + * Enumeration representing the possible states of a task in the A2A protocol. + * Tasks progress through various states from submission to completion or termination. */ public enum TaskState { + /** Task has been submitted and is waiting to be processed */ SUBMITTED("submitted"), + + /** Task is currently being processed by the agent */ WORKING("working"), + + /** Task requires additional input from the user to continue */ INPUT_REQUIRED("input-required"), + + /** Task requires authentication or authorization to proceed */ AUTH_REQUIRED("auth-required"), + + /** Task has been successfully completed */ COMPLETED("completed", true), + + /** Task has been canceled by the user or system */ CANCELED("canceled", true), + + /** Task has failed due to an error or exception */ FAILED("failed", true), + + /** Task has been rejected by the agent (e.g., invalid request) */ REJECTED("rejected", true), + + /** Task state is unknown or could not be determined */ UNKNOWN("unknown", true); + /** The string representation of this state for JSON serialization */ private final String state; + + /** Whether this state represents a final/terminal state */ private final boolean isFinal; + /** + * Constructs a TaskState with the specified string representation. + * The state is considered non-final by default. + * + * @param state the string representation of this state + */ TaskState(String state) { this(state, false); } + /** + * Constructs a TaskState with the specified string representation and finality. + * + * @param state the string representation of this state + * @param isFinal whether this state is final/terminal + */ TaskState(String state, boolean isFinal) { this.state = state; this.isFinal = isFinal; } + /** + * Returns the string representation of this state for JSON serialization. + * + * @return the state string + */ @JsonValue public String asString() { return state; } + /** + * Checks whether this state represents a final/terminal state. + * Final states indicate that the task has reached its end and will not transition further. + * + * @return {@code true} if this is a final state, {@code false} otherwise + */ public boolean isFinal(){ return isFinal; } + /** + * Creates a TaskState from its string representation. + * This method is used for JSON deserialization. + * + * @param state the string representation of the task state + * @return the corresponding TaskState enum value + * @throws IllegalArgumentException if the state string is not recognized + */ @JsonCreator public static TaskState fromString(String state) { switch (state) { diff --git a/spec/src/main/java/io/a2a/spec/TaskStatus.java b/spec/src/main/java/io/a2a/spec/TaskStatus.java index 2befdfcbf..d5a4749a2 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatus.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatus.java @@ -9,18 +9,39 @@ import io.a2a.util.Assert; /** - * Represents the status of a task. + * Represents the current status of a task in the A2A protocol. + * Contains the task's current state, an optional status message, and a timestamp + * indicating when this status was recorded. + * + * @param state the current state of the task (e.g., pending, in_progress, completed, failed) + * @param message an optional message providing additional context about the current status + * @param timestamp when this status was recorded (automatically set to current time if null) */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public record TaskStatus(TaskState state, Message message, @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS") LocalDateTime timestamp) { + /** + * Compact constructor that validates and initializes the task status. + *

+ * This constructor ensures that the task state is not null and automatically + * sets the timestamp to the current time if it is not provided. + *

+ * + * @throws IllegalArgumentException if state is null + */ public TaskStatus { Assert.checkNotNullParam("state", state); timestamp = timestamp == null ? LocalDateTime.now() : timestamp; } + /** + * Convenience constructor for creating a TaskStatus with only a state. + * The message will be null and timestamp will be set to the current time. + * + * @param state the current state of the task + */ public TaskStatus(TaskState state) { this(state, null, null); } diff --git a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java index 7a44480da..d61e656f5 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java @@ -9,26 +9,79 @@ import io.a2a.util.Assert; /** - * A task status update event. + * Represents a task status update event in the A2A protocol. + * + * This event is emitted when a task's status changes during execution, + * providing real-time updates about task progress, completion, or failure. + * It implements both {@link EventKind} and {@link StreamingEventKind} to support + * different event processing patterns in the A2A framework. + * + * The event contains information about which task was updated, its new status, + * the context it belongs to, whether this is a final status change, and any + * additional metadata associated with the status update. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public final class TaskStatusUpdateEvent implements EventKind, StreamingEventKind { public static final String STATUS_UPDATE = "status-update"; + /** + * The unique identifier of the task whose status was updated. + */ private final String taskId; + + /** + * The new status of the task after the update. + */ private final TaskStatus status; + + /** + * The identifier of the context/conversation this task belongs to. + */ private final String contextId; + + /** + * Indicates whether this status update represents a final state. + * If true, no further status updates are expected for this task. + */ private final boolean isFinal; + + /** + * Additional metadata associated with this status update. + * Can contain implementation-specific information about the status change. + */ private final Map metadata; + + /** + * The kind/type of this event, always "status-update" for TaskStatusUpdateEvent instances. + */ private final String kind; + /** + * Constructs a new TaskStatusUpdateEvent with the specified properties. + * + * @param taskId the unique identifier of the task whose status was updated + * @param status the new status of the task after the update + * @param contextId the identifier of the context/conversation this task belongs to + * @param isFinal whether this status update represents a final state + * @param metadata additional metadata associated with this status update + */ public TaskStatusUpdateEvent(String taskId, TaskStatus status, String contextId, boolean isFinal, Map metadata) { this(taskId, status, contextId, isFinal, metadata, STATUS_UPDATE); } + /** + * JSON constructor for creating TaskStatusUpdateEvent instances from JSON data. + * + * @param taskId the unique identifier of the task whose status was updated + * @param status the new status of the task after the update + * @param contextId the identifier of the context/conversation this task belongs to + * @param isFinal whether this status update represents a final state + * @param metadata additional metadata associated with this status update + * @param kind the kind/type of this event + */ @JsonCreator public TaskStatusUpdateEvent(@JsonProperty("taskId") String taskId, @JsonProperty("status") TaskStatus status, @JsonProperty("contextId") String contextId, @JsonProperty("final") boolean isFinal, @@ -48,32 +101,65 @@ public TaskStatusUpdateEvent(@JsonProperty("taskId") String taskId, @JsonPropert this.kind = kind; } + /** + * Gets the unique identifier of the task whose status was updated. + * + * @return the task ID + */ public String getTaskId() { return taskId; } + /** + * Gets the new status of the task after the update. + * + * @return the task status + */ public TaskStatus getStatus() { return status; } + /** + * Gets the identifier of the context/conversation this task belongs to. + * + * @return the context ID + */ public String getContextId() { return contextId; } + /** + * Indicates whether this status update represents a final state. + * + * @return true if this is a final status update, false otherwise + */ @JsonProperty("final") public boolean isFinal() { return isFinal; } + /** + * Gets the additional metadata associated with this status update. + * + * @return the metadata map + */ public Map getMetadata() { return metadata; } + /** + * Gets the kind/type of this event. + * + * @return the event kind, always "status-update" for TaskStatusUpdateEvent instances + */ @Override public String getKind() { return kind; } + /** + * Builder class for constructing {@link TaskStatusUpdateEvent} instances. + */ public static class Builder { private String taskId; private TaskStatus status; @@ -81,31 +167,66 @@ public static class Builder { private boolean isFinal; private Map metadata; + /** + * Sets the unique identifier of the task whose status was updated. + * + * @param id the task ID + * @return this builder instance + */ public Builder taskId(String id) { this.taskId = id; return this; } + /** + * Sets the new status of the task after the update. + * + * @param status the task status + * @return this builder instance + */ public Builder status(TaskStatus status) { this.status = status; return this; } + /** + * Sets the identifier of the context/conversation this task belongs to. + * + * @param contextId the context ID + * @return this builder instance + */ public Builder contextId(String contextId) { this.contextId = contextId; return this; } + /** + * Sets whether this status update represents a final state. + * + * @param isFinal true if this is a final status update, false otherwise + * @return this builder instance + */ public Builder isFinal(boolean isFinal) { this.isFinal = isFinal; return this; } + /** + * Sets the additional metadata associated with this status update. + * + * @param metadata the metadata map + * @return this builder instance + */ public Builder metadata(Map metadata) { this.metadata = metadata; return this; } + /** + * Builds and returns a new {@link TaskStatusUpdateEvent} instance with the configured properties. + * + * @return a new TaskStatusUpdateEvent instance + */ public TaskStatusUpdateEvent build() { return new TaskStatusUpdateEvent(taskId, status, contextId, isFinal, metadata); } diff --git a/spec/src/main/java/io/a2a/spec/TextPart.java b/spec/src/main/java/io/a2a/spec/TextPart.java index 1b62cf747..ec9494440 100644 --- a/spec/src/main/java/io/a2a/spec/TextPart.java +++ b/spec/src/main/java/io/a2a/spec/TextPart.java @@ -9,19 +9,45 @@ import io.a2a.util.Assert; /** + * A text content part that contains string content. + * This is one of the most common part types used for textual communication + * in the A2A protocol. + * * A fundamental text unit of an Artifact or Message. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class TextPart extends Part { + /** + * The text content of this part. + */ private final String text; + + /** + * Additional metadata associated with this text part. + */ private final Map metadata; + + /** + * The kind of this part, always TEXT for TextPart instances. + */ private final Kind kind; + /** + * Constructs a new TextPart with the specified text content and no metadata. + * + * @param text the text content + */ public TextPart(String text) { this(text, null); } + /** + * Constructs a new TextPart with the specified text content and metadata. + * + * @param text the text content + * @param metadata additional metadata for this text part + */ @JsonCreator public TextPart(@JsonProperty("text") String text, @JsonProperty("metadata") Map metadata) { Assert.checkNotNullParam("text", text); @@ -30,15 +56,30 @@ public TextPart(@JsonProperty("text") String text, @JsonProperty("metadata") Map this.kind = Kind.TEXT; } + /** + * Returns the kind of this part. + * + * @return the part kind, always Kind.TEXT + */ @Override public Kind getKind() { return kind; } + /** + * Returns the text content of this part. + * + * @return the text content + */ public String getText() { return text; } + /** + * Returns the metadata associated with this text part. + * + * @return the metadata map + */ @Override public Map getMetadata() { return metadata; diff --git a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java index d5ee0fb44..9685fee8e 100644 --- a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java +++ b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java @@ -7,12 +7,40 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * Represents a JSON-RPC 2.0 error indicating that a requested operation is not supported. + * This error is returned when a client attempts to invoke a method or perform an action + * that is not implemented or available in the current agent configuration. + * + *

Common scenarios where this error occurs:

+ *
    + *
  • Calling a method that is not implemented by the agent
  • + *
  • Requesting features that are disabled in the current configuration
  • + *
  • Using deprecated methods that are no longer supported
  • + *
  • Attempting operations that require capabilities not available in this agent version
  • + *
+ * + *

The error follows JSON-RPC 2.0 error object specification with a default + * error code of -32004 and a descriptive message. Additional context about + * the unsupported operation can be provided through the data field.

+ * + * @see JSONRPCError + */ @JsonInclude(JsonInclude.Include.NON_ABSENT) @JsonIgnoreProperties(ignoreUnknown = true) public class UnsupportedOperationError extends JSONRPCError { + /** Default error code for unsupported operation errors */ public final static Integer DEFAULT_CODE = -32004; + /** + * Creates an UnsupportedOperationError with custom values. + * Any null parameters will be replaced with default values. + * + * @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, such as the unsupported method name (can be null) + */ @JsonCreator public UnsupportedOperationError( @JsonProperty("code") Integer code, @@ -24,6 +52,10 @@ public UnsupportedOperationError( data); } + /** + * Creates an UnsupportedOperationError with default values. + * Uses the default error code and message. + */ public UnsupportedOperationError() { this(null, null, null); }