diff --git a/packages/a2a_dart/.gitignore b/packages/a2a_dart/.gitignore new file mode 100644 index 000000000..3a8579040 --- /dev/null +++ b/packages/a2a_dart/.gitignore @@ -0,0 +1,3 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ diff --git a/packages/a2a_dart/CHANGELOG.md b/packages/a2a_dart/CHANGELOG.md new file mode 100644 index 000000000..d7e0001f7 --- /dev/null +++ b/packages/a2a_dart/CHANGELOG.md @@ -0,0 +1,5 @@ +# a2a_dart Change Log + +## 0.1.0 + +- Initial version of the Dart A2A library. diff --git a/packages/a2a_dart/DESIGN.md b/packages/a2a_dart/DESIGN.md new file mode 100644 index 000000000..eb465f381 --- /dev/null +++ b/packages/a2a_dart/DESIGN.md @@ -0,0 +1,200 @@ +# A2A Dart Library Design Document + +## 1. Overview + +This document outlines the design for a pure Dart implementation of the Agent2Agent (A2A) protocol. The `a2a_dart` library provides both client and server components for A2A communication. The client is platform-independent and can be used in web applications, while the server is designed for native platforms that support `dart:io`. + +The primary goal is to create a library that is: + +- **Comprehensive**: Implements the full A2A specification. +- **Idiomatic**: Feels natural to Dart and Flutter developers. +- **Type-Safe**: Leverages Dart's strong type system to prevent errors. +- **Extensible**: Allows for future expansion and customization. + +## 2. Goals and Non-Goals + +### Goals + +- Provide a type-safe, idiomatic Dart implementation of the A2A protocol. +- Support the full A2A specification, including all data models and RPC methods. +- Offer a clear and easy-to-use client API for interacting with A2A agents. +- Provide a flexible and extensible server framework for building A2A agents in Dart. +- Adhere to Dart and Flutter best practices, including null safety, effective asynchronous programming, and clean architecture. + +### Non-Goals + +- **Transports**: Implement transport protocols other than JSON-RPC and SSE over HTTP. gRPC and REST transports are out of scope for the initial version. +- **Push Notifications**: The server-side push notification mechanism will not be implemented initially. The client will support sending the configuration, but the server will not act on it. +- **Agent Framework**: Provide a full-fledged agent framework with built-in AI capabilities. This library focuses on the communication protocol. +- **Extensions**: Implement any of the optional extensions to the A2A protocol in the initial version. + +## 3. Implemented A2A Features + +The `a2a_dart` library implements the following features from the A2A specification: + +### Core Concepts + +- **Client & Server**: Foundational components for initiating and responding to A2A requests. +- **Agent Card**: Full implementation for agent discovery and capability advertisement. +- **Task**: State management for all agent operations. +- **Message**: The primary object for communication turns. +- **Part**: Support for `TextPart`, `FilePart`, and `DataPart` to enable rich content exchange. +- **Artifact**: Handling for agent-generated outputs. +- **Context**: Grouping related tasks. + +### Transport Protocols + +- **JSON-RPC 2.0**: The primary transport protocol for all RPC methods over HTTP/S. +- **Server-Sent Events (SSE)**: For real-time, streaming updates from the server to the client (`message/stream` and `tasks/resubscribe`). + +### Data Models + +- A complete, type-safe implementation of all data objects defined in the specification, including: + - `Task`, `TaskStatus`, `TaskState` + - `Message`, `Part` (and its variants) + - `AgentCard` (and all nested objects like `AgentSkill`, `AgentProvider`, etc.) + - `Artifact` + - `PushNotificationConfig` (client-side only) + - All JSON-RPC request, response, and error structures. + +### RPC Methods + +- The library provides client methods and server-side handlers for the following A2A RPC methods: + - `get_agent_card` (via HTTP GET) + - `create_task` + - `message/stream` + - `execute_task` + +### Authentication + +- The library will be designed to work with standard HTTP authentication mechanisms (e.g., Bearer Token, API Key) by providing hooks (middleware) for adding authentication headers to client requests. + +## 4. Architecture + +The `a2a_dart` library is structured with a single public entry point, `lib/a2a_dart.dart`, which exports the core, client, and server APIs. The internal structure is organized as follows: + +- **`lib/src`**: Contains the private implementation of the library. + - **`core`**: Contains the platform-independent data models and types defined in the A2A specification. + - **`client`**: Provides the `A2AClient` class and transport implementations (`HttpTransport`, `SseTransport`). + - **`server`**: Offers a framework for building A2A agents. It uses a conditional export (`a2a_server.dart`) to provide a native implementation (`io/a2a_server.dart`) and a web stub (`web/a2a_server.dart`). + +```mermaid +graph TD + subgraph Public API + A[lib/a2a_dart.dart] + end + + subgraph "Implementation (lib/src)" + B[Core] + C[Client] + D[Server] + end + + A --> B + A --> C + A --> D + + B --> B1[Data Models] + + C --> C1[A2AClient] + C --> C2[Transport] + C2 --> C2a[HttpTransport] + C2 --> C2b[SseTransport] + + D --> D1[a2a_server.dart (conditional export)] + D1 --> D1a[io/a2a_server.dart] + D1 --> D1b[web/a2a_server.dart] + D --> D2[RequestHandler] +``` + +## 4. Data Models + +All data models from the A2A specification will be implemented as immutable Dart classes. To reduce boilerplate and ensure correctness, we will use the `json_serializable` and `freezed` packages for JSON serialization and value equality. + +- **Immutability**: All model classes will be immutable. +- **JSON Serialization**: Each class will have `fromJson` and `toJson` methods. +- **Null Safety**: All fields will be null-safe. + +Example `AgentCard` model: + +```dart +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'agent_card.freezed.dart'; +part 'agent_card.g.dart'; + +@freezed +class AgentCard with _$AgentCard { + const factory AgentCard({ + required String protocolVersion, + required String name, + required String description, + required String url, + // ... other fields + }) = _AgentCard; + + factory AgentCard.fromJson(Map json) => _$AgentCardFromJson(json); +} +``` + +## 5. Client API + +The client API will be centered around the `A2AClient` class. This class will provide methods for each of the A2A RPC calls, such as `sendMessage`, `getTask`, and `cancelTask`. + +- **Asynchronous**: All API methods will be asynchronous, returning `Future`s. +- **Transport Agnostic**: The `A2AClient` delegates the actual HTTP communication to a `Transport` interface. This allows for different transport implementations, with `HttpTransport` providing basic request-response and `SseTransport` extending it for streaming. + +Example `A2AClient` usage: + +```dart +final log = Logger('MyClient'); +final client = A2AClient( + url: 'https://example.com/a2a', + transport: SseTransport(url: 'https://example.com/a2a', log: log), +); + +// Create a task +final task = await client.createTask(Message( + messageId: '1', + role: Role.user, + parts: [Part.text(text: 'Hello, agent!')], +)); + +// Execute the task and get a stream of events +final stream = client.executeTask(task.id); +await for (final event in stream) { + // process events +} +``` + +## 6. Server Framework + +The server framework will provide the building blocks for creating A2A-compliant agents in Dart. + +- **`A2AServer`**: A top-level class that listens for incoming HTTP requests. It is conditionally exported to support both native and web platforms. On native, it uses `dart:io` to create an HTTP server. On the web, it throws an `UnsupportedError` if instantiated. +- **`RequestHandler`**: An interface for handling specific A2A methods. Developers will implement this interface to define their agent's behavior. The `handle` method returns a `HandlerResult` which can be a `SingleResult` for a single response or a `StreamResult` for a streaming response. +- **`TaskManager`**: A class responsible for managing the lifecycle of tasks. + +## 7. Error Handling + +Errors will be handled using a combination of exceptions and a `Result` type. Network and transport-level errors will throw exceptions, while A2A-specific errors will be returned as part of a `Result` object, allowing for more granular error handling. + +## 8. Dependencies + +- `http`: For making HTTP requests. +- `freezed`: For immutable data classes. +- `json_serializable`: For JSON serialization. +- `shelf`: For building the server. +- `shelf_router`: For routing requests on the server. +- `uuid`: For generating unique IDs. + +## 9. Testing + +The library will have a comprehensive suite of unit and integration tests. + +- **Unit Tests**: Will cover individual classes and methods in isolation. +- **Integration Tests**: Will test the client and server components together, as well as against a known-good A2A implementation. + +## 10. Documentation + +All public APIs will be thoroughly documented with DartDoc comments. The package will also include a comprehensive `README.md` and example usage. diff --git a/packages/a2a_dart/GEMINI.md b/packages/a2a_dart/GEMINI.md new file mode 100644 index 000000000..77036dcef --- /dev/null +++ b/packages/a2a_dart/GEMINI.md @@ -0,0 +1,59 @@ +# A2A Dart Package + +## Overview + +This package provides a Dart implementation of the A2A (Agent-to-Agent) protocol. It includes a client for interacting with A2A servers and a server framework for building A2A agents. + +Here's the overview of the layout of this pacakge: + +``` +├── analysis_options.yaml +├── lib +│ ├── a2a_dart.dart +│ └── src +│ ├── client +│ │ ├── a2a_client.dart +│ │ ├── transport.dart +│ │ ├── http_transport.dart +│ │ └── sse_transport.dart +│ ├── core +│ │ ├── agent_card.dart +│ │ ├── message.dart +│ │ ├── task.dart +│ │ └── ... (other data models) +│ └── server +│ ├── a2a_server.dart (conditional export) +│ ├── request_handler.dart +│ ├── io +│ │ └── a2a_server.dart (native implementation) +│ └── web +│ └── a2a_server.dart (web stub) +├── pubspec.yaml +└── test + ├── client + │ └── a2a_client_test.dart + ├── integration + │ └── client_server_test.dart + └── server + └── a2a_server_test.dart +``` + +## Documentation and References + +The design document in the `DESIGN.md` file provides an overview of the package's architecture and design decisions. + +The high level overview of the package in the `README.md` file. + +The A2A protocol specification is defined here: [A2A Protocol](https://a2a-protocol.org/latest/specification/). + +## Client + +`A2AClient` interacts with A2A servers. It supports RPC calls like `get_agent_card`, `create_task`, and `execute_task`. Communication is handled by a `Transport` interface, with `HttpTransport` for single requests and `SseTransport` for streaming. + +## Server + +`A2AServer` is a framework for building A2A agents on top of the `shelf` package. It uses a pipeline of `RequestHandler` instances to process requests, where each handler corresponds to an RPC method. The `handle` method returns a `HandlerResult`, which can be a `SingleResult` for one response or a `StreamResult` for a stream of responses. + +## Data Models + +The package includes Dart classes for A2A data structures (`AgentCard`, `Message`, `Task`, `SecurityScheme`). These are built with `freezed` and `json_serializable` to be immutable and support JSON serialization. diff --git a/packages/a2a_dart/LICENSE b/packages/a2a_dart/LICENSE new file mode 100644 index 000000000..650b89564 --- /dev/null +++ b/packages/a2a_dart/LICENSE @@ -0,0 +1,26 @@ +Copyright 2025 The Flutter Authors. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/packages/a2a_dart/README.md b/packages/a2a_dart/README.md new file mode 100644 index 000000000..5a77828b2 --- /dev/null +++ b/packages/a2a_dart/README.md @@ -0,0 +1,75 @@ +# A2A Dart + +This package provides a Dart implementation of the A2A (Agent-to-Agent) protocol. It includes a client for interacting with A2A servers and a server framework for building A2A agents. + +## Features + +- **A2A Client**: A high-level client for communicating with A2A servers. +- **HTTP and SSE Transports**: Support for both standard request-response and streaming communication. +- **A2A Server**: A simple and extensible server framework. +- **Type-Safe Data Models**: Dart classes for all A2A data structures. +- **Web Compatible**: The client can be used in web applications. + +## Installation + +Add the following to your `pubspec.yaml` file: + +```yaml +dependencies: + a2a_dart: ^0.1.0 # or the latest version +``` + +## Usage + +### Client + +```dart +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:logging/logging.dart'; + +void main() async { + final log = Logger('A2AClient'); + // For streaming, use SseTransport. + final transport = SseTransport(url: 'http://localhost:8080', log: log); + final client = A2AClient(url: 'http://localhost:8080', transport: transport); + + // Get the agent card. + final agentCard = await client.getAgentCard(); + print('Agent: ${agentCard.name}'); + + // Create a new task. + final message = Message( + messageId: '1', + role: Role.user, + parts: [Part.text(text: 'Hello')], + ); + final task = await client.createTask(message); + print('Created task: ${task.id}'); + + // Execute the task and stream the results. + try { + final stream = client.executeTask(task.id); + await for (final event in stream) { + print('Received event: ${event.type}'); + } + } on A2AException catch (e) { + print('Error executing task: ${e.message}'); + } +} +``` + +### Server + +```dart +import 'package:a2a_dart/a2a_dart.dart'; + +void main() async { + final taskManager = TaskManager(); + final server = A2AServer([ + CreateTaskHandler(taskManager), + ]); + + await server.start(); + print('Server started on port ${server.port}'); +} +``` diff --git a/packages/a2a_dart/a2a_spec.md b/packages/a2a_dart/a2a_spec.md new file mode 100644 index 000000000..4cc1e9966 --- /dev/null +++ b/packages/a2a_dart/a2a_spec.md @@ -0,0 +1,2158 @@ +# Agent2Agent (A2A) Protocol Official Specification + +{% macro render_spec_tabs(region_tag) %} +=== "JSON-RPC" + + ```ts { .no-copy } + --8<-- "types/src/types.ts:{{ region_tag }}" + ``` + +=== "gRPC" + + ```proto { .no-copy } + --8<-- "specification/grpc/a2a.proto:{{ region_tag }}" + ``` +{% endmacro %} + +??? note "**Latest Released Version** [`0.3.0`](https://a2a-protocol.org/v0.3.0/specification)" + + **Previous Versions** + + - [`0.2.6`](https://a2a-protocol.org/v0.2.6/specification) + - [`0.2.5`](https://a2a-protocol.org/v0.2.5/specification) + - [`0.2.4`](https://a2a-protocol.org/v0.2.4/specification) + - [`0.2.0`](https://a2a-protocol.org/v0.2.0/specification) + - [`0.1.0`](https://a2a-protocol.org/v0.1.0/specification) + +See [Release Notes](https://github.com/a2aproject/A2A/releases) for changes made between versions. + +## 1. Introduction + +The Agent2Agent (A2A) Protocol is an open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems. In an ecosystem where agents might be built using different frameworks, languages, or by different vendors, A2A provides a common language and interaction model. + +This document provides the detailed technical specification for the A2A protocol. Its primary goal is to enable agents to: + +- Discover each other's capabilities. +- Negotiate interaction modalities (text, files, structured data). +- Manage collaborative tasks. +- Securely exchange information to achieve user goals **without needing access to each other's internal state, memory, or tools.** + +### 1.1. Key Goals of A2A + +- **Interoperability:** Bridge the communication gap between disparate agentic systems. +- **Collaboration:** Enable agents to delegate tasks, exchange context, and work together on complex user requests. +- **Discovery:** Allow agents to dynamically find and understand the capabilities of other agents. +- **Flexibility:** Support various interaction modes including synchronous request/response, streaming for real-time updates, and asynchronous push notifications for long-running tasks. +- **Security:** Facilitate secure communication patterns suitable for enterprise environments, relying on standard web security practices. +- **Asynchronicity:** Natively support long-running tasks and interactions that may involve human-in-the-loop scenarios. + +### 1.2. Guiding Principles + +- **Simple:** Reuse existing, well-understood standards (HTTP, JSON-RPC 2.0, Server-Sent Events). +- **Enterprise Ready:** Address authentication, authorization, security, privacy, tracing, and monitoring by aligning with established enterprise practices. +- **Async First:** Designed for (potentially very) long-running tasks and human-in-the-loop interactions. +- **Modality Agnostic:** Support exchange of diverse content types including text, audio/video (via file references), structured data/forms, and potentially embedded UI components (e.g., iframes referenced in parts). +- **Opaque Execution:** Agents collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations. + +For a broader understanding of A2A's purpose and benefits, see [What is A2A?](./topics/what-is-a2a.md). + +## 2. Core Concepts Summary + +A2A revolves around several key concepts. For detailed explanations, please refer to the [Key Concepts guide](./topics/key-concepts.md). + +- **A2A Client:** An application or agent that initiates requests to an A2A Server on behalf of a user or another system. +- **A2A Server (Remote Agent):** An agent or agentic system that exposes an A2A-compliant HTTP endpoint, processing tasks and providing responses. +- **Agent Card:** A JSON metadata document published by an A2A Server, describing its identity, capabilities, skills, service endpoint, and authentication requirements. +- **Message:** A communication turn between a client and a remote agent, having a `role` ("user" or "agent") and containing one or more `Parts`. +- **Task:** The fundamental unit of work managed by A2A, identified by a unique ID. Tasks are stateful and progress through a defined lifecycle. +- **Part:** The smallest unit of content within a Message or Artifact (e.g., `TextPart`, `FilePart`, `DataPart`). +- **Artifact:** An output (e.g., a document, image, structured data) generated by the agent as a result of a task, composed of `Parts`. +- **Streaming (SSE):** Real-time, incremental updates for tasks (status changes, artifact chunks) delivered via Server-Sent Events. +- **Push Notifications:** Asynchronous task updates delivered via server-initiated HTTP POST requests to a client-provided webhook URL, for long-running or disconnected scenarios. +- **Context:** An optional, server-generated identifier to logically group related tasks. +- **Extension:** A mechanism for agents to provide additional functionality or data beyond the core A2A specification. + +## 3. Transport and Format + +### 3.1. Transport Layer Requirements + +A2A supports multiple transport protocols, all operating over **HTTP(S)**. Agents have flexibility in choosing which transport protocols to implement based on their specific requirements and use cases: + +- A2A communication **MUST** occur over **HTTP(S)**. +- The A2A Server exposes its service at one or more URLs defined in its `AgentCard`. +- Agents **MUST** implement at least one of the three core transport protocols defined in this specification. +- All supported transport protocols are considered equal in status and capability. + +### 3.2. Supported Transport Protocols + +A2A defines three core transport protocols. **A2A-compliant agents SHOULD implement at least one of these transport protocols. They MAY be compliant implementing a transport extension as defined in [3.2.4](#324-transport-extensions)** All three protocols are considered equal in status, and agents may choose to implement any combination of them based on their requirements. + +#### 3.2.1. JSON-RPC 2.0 Transport + +Agents **MAY** support JSON-RPC 2.0 transport. If implemented, it **MUST** conform to these requirements: + +- The primary data format is **[JSON-RPC 2.0](https://www.jsonrpc.org/specification)** for all requests and responses (excluding SSE stream wrapper). +- Client requests and server responses **MUST** adhere to the JSON-RPC 2.0 specification. +- The `Content-Type` header for HTTP requests and responses containing JSON-RPC payloads **MUST** be `application/json`. +- Method names follow the pattern `{category}/{action}` (e.g., `"message/send"`, `"tasks/get"`). + +#### 3.2.2. gRPC Transport + +Agents **MAY** support gRPC transport. If implemented, it **MUST** conform to these requirements: + +- **Protocol Definition**: **MUST** use the normative Protocol Buffers definition in [`specification/grpc/a2a.proto`](https://github.com/a2aproject/A2A/blob/main/specification/grpc/a2a.proto). +- **Message Serialization**: **MUST** use Protocol Buffers version 3 for message serialization. +- **Service Definition**: **MUST** implement the `A2AService` gRPC service as defined in the proto file. +- **Method Coverage**: **MUST** provide all methods with functionally equivalent behavior to other supported transports. +- **Field Mapping**: **MUST** use the `json_name` annotations for HTTP/JSON transcoding compatibility. +- **Error Handling**: **MUST** map A2A error codes to appropriate gRPC status codes as defined in the proto annotations. +- **Transport Security**: **MUST** support TLS encryption (gRPC over HTTP/2 with TLS). + +#### 3.2.3. HTTP+JSON/REST Transport + +Agents **MAY** support REST-style HTTP+JSON transport. If implemented, it **MUST** conform to these requirements: + +- **HTTP Methods**: **MUST** use appropriate HTTP verbs (GET for queries, POST for actions, PUT for updates, DELETE for removal). +- **URL Patterns**: **MUST** follow the URL patterns documented in each method section (e.g., `/v1/message:send`, `/v1/tasks/{id}`). +- **Content-Type**: **MUST** use `application/json` for request and response bodies. +- **HTTP Status Codes**: **MUST** use appropriate HTTP status codes (200, 400, 401, 403, 404, 500, etc.) that correspond to A2A error types. +- **Request/Response Format**: **MUST** use JSON objects that are structurally equivalent to the core A2A data structures. +- **Method Coverage**: **MUST** provide all methods with functionally equivalent behavior to other supported transports. +- **Error Format**: **MUST** return error responses in a consistent JSON format that maps to A2A error types. + +#### 3.2.4. Transport Extensions + +Additional transport protocols **MAY** be defined as extensions to the core A2A specification. Such extensions: + +- **MUST** maintain functional equivalence with the core transports +- **MUST** use clear namespace identifiers to avoid conflicts +- **MUST** be clearly documented and specified +- **SHOULD** provide migration paths from core transports + +### 3.3. Streaming Transport (Server-Sent Events) + +Streaming capabilities are **transport-specific**: + +#### 3.3.1. JSON-RPC 2.0 Streaming + +When streaming is used for methods like `message/stream` or `tasks/resubscribe`: + +- The server responds with an HTTP `200 OK` status and a `Content-Type` header of `text/event-stream`. +- The body of this HTTP response contains a stream of **[Server-Sent Events (SSE)](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events)** as defined by the W3C. +- Each SSE `data` field contains a complete JSON-RPC 2.0 Response object (specifically, a [`SendStreamingMessageResponse`](#721-sendstreamingmessageresponse-object)). + +#### 3.3.2. gRPC Streaming + +gRPC transport uses **server streaming RPCs** for streaming operations as defined in the Protocol Buffers specification. + +#### 3.3.3. HTTP+JSON/REST Streaming + +If REST transport is supported it **MUST** implement streaming using Server-Sent Events similar to JSON-RPC. + +### 3.4. Transport Compliance and Interoperability + +#### 3.4.1. Functional Equivalence Requirements + +When an agent supports multiple transports, all supported transports **MUST**: + +- **Identical Functionality**: Provide the same set of operations and capabilities. +- **Consistent Behavior**: Return semantically equivalent results for the same requests. +- **Same Error Handling**: Map errors consistently across transports using the error codes defined in [Section 8](#8-error-handling). +- **Equivalent Authentication**: Support the same authentication schemes declared in the `AgentCard`. + +#### 3.4.2. Transport Selection and Negotiation + +- **Agent Declaration**: Agents **MUST** declare all supported transports in their `AgentCard` using the `preferredTransport` and `additionalInterfaces` fields. +- **Client Choice**: Clients **MAY** choose any transport declared by the agent. +- **No Transport Negotiation**: A2A does not define a dynamic transport negotiation protocol. Clients select a transport based on the static `AgentCard` information. +- **Fallback Behavior**: Clients **SHOULD** implement fallback logic to try alternative transports if their preferred transport fails. The specific fallback strategy is implementation-dependent. + +#### 3.4.3. Transport-Specific Extensions + +Transports **MAY** provide transport-specific optimizations or extensions that do not compromise functional equivalence: + +- **gRPC**: May leverage gRPC-specific features like bidirectional streaming, metadata, or custom status codes. +- **REST**: May provide additional HTTP caching headers or support HTTP conditional requests. +- **JSON-RPC**: May include additional fields in the JSON-RPC request/response objects that do not conflict with the core specification. + +Such extensions **MUST** be backward-compatible and **MUST NOT** break interoperability with clients that do not support the extensions. + +### 3.5. Method Mapping and Naming Conventions + +To ensure consistency and predictability across different transports, A2A defines normative method mapping rules. + +#### 3.5.1. JSON-RPC Method Naming + +JSON-RPC methods **MUST** follow the pattern: `{category}/{action}` where: + +- `category` represents the resource type (e.g., "message", "tasks", "agent") +- `action` represents the operation (e.g., "send", "get", "cancel") +- Nested actions use forward slashes (e.g., "tasks/pushNotificationConfig/set") + +#### 3.5.2. gRPC Method Naming + +gRPC methods **MUST** follow Protocol Buffers service conventions using PascalCase: + +- Convert JSON-RPC category/action to PascalCase compound words +- Use standard gRPC method prefixes (Get, Set, List, Create, Delete, Cancel) + +#### 3.5.3. HTTP+JSON/REST Method Naming + +REST endpoints **MUST** follow RESTful URL patterns with appropriate HTTP verbs: + +- Use resource-based URLs: `/v1/{resource}[/{id}][:{action}]` +- Use standard HTTP methods aligned with REST semantics +- Use colon notation for non-CRUD actions + +#### 3.5.4. Method Mapping Compliance + +When implementing multiple transports, agents **MUST**: + +- **Use standard mappings**: Follow the method mappings defined in sections 3.5.2 and 3.5.3. +- **Maintain functional equivalence**: Each transport-specific method **MUST** provide identical functionality across all supported transports. +- **Consistent parameters**: Use equivalent parameter structures across transports (accounting for transport-specific serialization differences). +- **Equivalent responses**: Return semantically equivalent responses across all transports for the same operation. + +#### 3.5.5. Extension Method Naming + +For custom or extension methods not defined in the core A2A specification: + +- **JSON-RPC**: Follow the `{category}/{action}` pattern with a clear namespace (e.g., `myorg.extension/action`) +- **gRPC**: Use appropriate service and method names following Protocol Buffers conventions +- **REST**: Use clear resource-based URLs with appropriate HTTP methods + +Extension methods **MUST** be clearly documented and **MUST NOT** conflict with core A2A method names or semantics. + +#### 3.5.6. Method Mapping Reference Table + +For quick reference, the following table summarizes the method mappings across all transports: + +| JSON-RPC Method | gRPC Method | REST Endpoint | Description | +|:----------------|:------------|:--------------|:------------| +| `message/send` | `SendMessage` | `POST /v1/message:send` | Send message to agent | +| `message/stream` | `SendStreamingMessage` | `POST /v1/message:stream` | Send message with streaming | +| `tasks/get` | `GetTask` | `GET /v1/tasks/{id}` | Get task status | +| `tasks/list` | `ListTask` | `GET /v1/tasks` | List tasks (gRPC/REST only) | +| `tasks/cancel` | `CancelTask` | `POST /v1/tasks/{id}:cancel` | Cancel task | +| `tasks/resubscribe` | `TaskSubscription` | `POST /v1/tasks/{id}:subscribe` | Resume task streaming | +| `tasks/pushNotificationConfig/set` | `CreateTaskPushNotification` | `POST /v1/tasks/{id}/pushNotificationConfigs` | Set push notification config | +| `tasks/pushNotificationConfig/get` | `GetTaskPushNotification` | `GET /v1/tasks/{id}/pushNotificationConfigs/{configId}` | Get push notification config | +| `tasks/pushNotificationConfig/list` | `ListTaskPushNotification` | `GET /v1/tasks/{id}/pushNotificationConfigs` | List push notification configs | +| `tasks/pushNotificationConfig/delete` | `DeleteTaskPushNotification` | `DELETE /v1/tasks/{id}/pushNotificationConfigs/{configId}` | Delete push notification config | +| `agent/getAuthenticatedExtendedCard` | `GetAgentCard` | `GET /v1/card` | Get authenticated agent card | + +## 4. Authentication and Authorization + +A2A treats agents as standard enterprise applications, relying on established web security practices. Identity information is **not** transmitted within A2A JSON-RPC payloads; it is handled at the HTTP transport layer. + +For a comprehensive guide on enterprise security aspects, see [Enterprise-Ready Features](./topics/enterprise-ready.md). + +### 4.1. Transport Security + +As stated in section 3.1, production deployments **MUST** use HTTPS. Implementations **SHOULD** use modern [TLS](https://datatracker.ietf.org/doc/html/rfc8446) configurations (TLS 1.3+ recommended) with strong cipher suites. + +### 4.2. Server Identity Verification + +A2A Clients **SHOULD** verify the A2A Server's identity by validating its TLS certificate against trusted certificate authorities (CAs) during the TLS handshake. + +### 4.3. Client/User Identity & Authentication Process + +1. **Discovery of Requirements:** The client discovers the server's required authentication schemes via the `authentication` field in the [`AgentCard`](#55-agentcard-object-structure). Scheme names often align with [OpenAPI Authentication methods](https://swagger.io/docs/specification/authentication/) (e.g., "Bearer" for OAuth 2.0 tokens, "Basic" for Basic Auth, "ApiKey" for API keys). +2. **Credential Acquisition (Out-of-Band):** The client obtains the necessary credentials (e.g., API keys, OAuth tokens, JWTs) through an **out-of-band process** specific to the required authentication scheme and the identity provider. This process is outside the scope of the A2A protocol itself. +3. **Credential Transmission:** The client includes these credentials in the appropriate [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) (e.g., `Authorization: Bearer `, `X-API-Key: `) of every A2A request sent to the server. + +### 4.4. Server Responsibilities for Authentication + +The A2A Server: + +- **MUST** authenticate every incoming request based on the provided HTTP credentials and its declared authentication requirements from its Agent Card. +- **SHOULD** use standard HTTP status codes like [`401 Unauthorized`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401) or [`403 Forbidden`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403) for authentication challenges or rejections. +- **SHOULD** include relevant HTTP headers (e.g., [`WWW-Authenticate`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate)) with `401 Unauthorized` responses to indicate the required authentication scheme(s), guiding the client. +- **SHOULD** verify the Client's webhook server identity by validating its TLS certificate against trusted certificate authorities (CAs) during the TLS handshake. + +### 4.5. In-Task Authentication (Secondary Credentials) + +If an agent, during the execution of a task, requires _additional_ credentials for a _different_ system or resource (e.g., to access a specific tool on behalf of the user that requires its own auth): + +1. It **SHOULD** transition the A2A task to the `auth-required` state (see [`TaskState`](#63-taskstate-enum)). +2. The accompanying `TaskStatus.message` (often a [`DataPart`](#653-datapart-object)) **SHOULD** provide details about the required secondary authentication, potentially using an [`PushNotificationAuthenticationInfo`](#69-pushnotificationauthenticationinfo-object)-like structure to describe the need. +3. The A2A Client then obtains these new credentials out-of-band and provides them in a subsequent [`message/send`](#71-messagesend) or [`message/stream`](#72-messagestream) request. How these credentials are used (e.g., passed as data within the A2A message if the agent is proxying, or used by the client to interact directly with the secondary system) depends on the specific scenario. + +### 4.6. Authorization + +Once a client is authenticated, the A2A Server is responsible for authorizing the request based on the authenticated client/user identity and its own policies. Authorization logic is implementation-specific and MAY be enforced based on: + +- The specific skills requested (e.g., as identified by `AgentSkill.id` from the Agent Card). +- The actions attempted within the task. +- Data access policies relevant to the resources the agent manages. +- OAuth scopes associated with the presented token, if applicable. + +Servers should implement the principle of least privilege. + +## 5. Agent Discovery: The Agent Card + +### 5.1. Purpose + +A2A Servers **MUST** make an Agent Card available. The Agent Card is a JSON document that describes the server's identity, capabilities, skills, service endpoint URL, and how clients should authenticate and interact with it. Clients use this information for discovering suitable agents and for configuring their interactions. + +For more on discovery strategies, see the [Agent Discovery guide](./topics/agent-discovery.md). + +### 5.2. Discovery Mechanisms + +Clients can find Agent Cards through various methods, including but not limited to: + +- **Well-Known URI:** Accessing a predefined path on the agent's domain (see [Section 5.3](#53-recommended-location)). +- **Registries/Catalogs:** Querying curated catalogs or registries of agents (which might be enterprise-specific, public, or domain-specific). +- **Direct Configuration:** Clients may be pre-configured with the Agent Card URL or the card content itself. + +### 5.3. Recommended Location + +If using the well-known URI strategy, the recommended location for an agent's Agent Card is: +`https://{server_domain}/.well-known/agent-card.json` +This follows the principles of [RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615) for well-known URIs. + +### 5.4. Security of Agent Cards + +Agent Cards themselves might contain information that is considered sensitive. + +- If an Agent Card contains sensitive information, the endpoint serving the card **MUST** be protected by appropriate access controls (e.g., mTLS, network restrictions, authentication required to fetch the card). +- It is generally **NOT RECOMMENDED** to include plaintext secrets (like static API keys) directly in an Agent Card. Prefer authentication schemes where clients obtain dynamic credentials out-of-band. + +### 5.5. `AgentCard` Object Structure + +{{ render_spec_tabs('AgentCard') }} + +#### 5.5.1. `AgentProvider` Object + +Information about the organization or entity providing the agent. + +{{ render_spec_tabs('AgentProvider') }} + +#### 5.5.2. `AgentCapabilities` Object + +Specifies optional A2A protocol features supported by the agent. + +{{ render_spec_tabs('AgentCapabilities') }} + +#### 5.5.2.1. `AgentExtension` Object + +Specifies an extension to the A2A protocol supported by the agent. + +{{ render_spec_tabs('AgentExtension') }} + +#### 5.5.3. `SecurityScheme` Object + +Describes the authentication requirements for accessing the agent's `url` endpoint. Refer [Sample Agent Card](#57-sample-agent-card) for an example. + +{{ render_spec_tabs('SecurityScheme') }} + +#### 5.5.4. `AgentSkill` Object + +Describes a specific capability, function, or area of expertise the agent can perform or address. + +{{ render_spec_tabs('AgentSkill') }} + +#### 5.5.5. `AgentInterface` Object + +Provides a declaration of a combination of the target URL and the supported transport to interact with the agent. This enables agents to expose the same functionality through multiple transport protocols. + +```ts { .no-copy } +--8<-- "types/src/types.ts:TransportProtocol" +``` + +{{ render_spec_tabs('AgentInterface') }} + +The `transport` field **SHOULD** use one of the core A2A transport protocol values: + +- `"JSONRPC"`: JSON-RPC 2.0 over HTTP +- `"GRPC"`: gRPC over HTTP/2 +- `"HTTP+JSON"`: REST-style HTTP with JSON + +Additional transport values **MAY** be used for future extensions, but such extensions **MUST** not conflict with core A2A protocol functionality. + +#### 5.5.6. `AgentCardSignature` Object + +Represents a JSON Web Signature (JWS) used to verify the integrity of the AgentCard. + +{{ render_spec_tabs('AgentCardSignature') }} + +### 5.6. Transport Declaration and URL Relationships + +The AgentCard **MUST** properly declare the relationship between URLs and transport protocols: + +#### 5.6.1. Main URL and Preferred Transport + +- **Main URL requirement**: The `url` field **MUST** specify the primary endpoint for the agent. +- **Transport correspondence**: The transport protocol available at the main `url` **MUST** match the `preferredTransport` field. +- **Required declaration**: The `preferredTransport` field is **REQUIRED** and **MUST** be present in every `AgentCard`. +- **Transport availability**: The main `url` **MUST** support the transport protocol declared in `preferredTransport`. + +#### 5.6.2. Additional Interfaces + +- **URL uniqueness**: Each `AgentInterface` in `additionalInterfaces` **SHOULD** specify a distinct URL for clarity, but **MAY** reuse URLs if multiple transport protocols are available at the same endpoint. +- **Transport declaration**: Each `AgentInterface` **MUST** accurately declare the transport protocol available at its specified URL. +- **Completeness**: The `additionalInterfaces` array **SHOULD** include all supported transports, including the main URL's transport for completeness. + +#### 5.6.3. Client Transport Selection Rules + +Clients **MUST** follow these rules when selecting a transport: + +1. **Parse transport declarations**: Extract available transports from both the main `url`/`preferredTransport` combination and all `additionalInterfaces`. +2. **Prefer declared preference**: If the client supports the `preferredTransport`, it **SHOULD** use the main `url`. +3. **Fallback selection**: If the preferred transport is not supported by the client, it **MAY** select any supported transport from `additionalInterfaces`. +4. **Graceful degradation**: Clients **SHOULD** implement fallback logic to try alternative transports if their first choice fails. +5. **URL-transport matching**: Clients **MUST** use the correct URL for the selected transport protocol as declared in the AgentCard. + +#### 5.6.4. Validation Requirements + +Agent Cards **MUST** satisfy these validation requirements: + +- **Transport consistency**: The `preferredTransport` value **MUST** be present and **MUST** be available at the main `url`. +- **Interface completeness**: If `additionalInterfaces` is provided, it **SHOULD** include an entry corresponding to the main `url` and `preferredTransport`. +- **No conflicts**: The same URL **MUST NOT** declare conflicting transport protocols across different interface declarations. +- **Minimum transport requirement**: The agent **MUST** declare at least one supported transport protocol through either the main `url`/`preferredTransport` combination or `additionalInterfaces`. + +### 5.7. Sample Agent Card + +```json +{ + "protocolVersion": "0.2.9", + "name": "GeoSpatial Route Planner Agent", + "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", + "url": "https://georoute-agent.example.com/a2a/v1", + "preferredTransport": "JSONRPC", + "additionalInterfaces" : [ + {"url": "https://georoute-agent.example.com/a2a/v1", "transport": "JSONRPC"}, + {"url": "https://georoute-agent.example.com/a2a/grpc", "transport": "GRPC"}, + {"url": "https://georoute-agent.example.com/a2a/json", "transport": "HTTP+JSON"} + ], + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [{ "google": ["openid", "profile", "email"] }], + "defaultInputModes": ["application/json", "text/plain"], + "defaultOutputModes": ["application/json", "image/png"], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": ["maps", "routing", "navigation", "directions", "traffic"], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}" + ], + "inputModes": ["application/json", "text/plain"], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": ["maps", "customization", "visualization", "cartography"], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": ["application/json"], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + } + ], + "supportsAuthenticatedExtendedCard": true, + "signatures": [ + { + "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", + "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" + } + ] +} +``` + +## 6. Protocol Data Objects + +These objects define the structure of data exchanged within the JSON-RPC methods of the A2A protocol. + +### 6.1. `Task` Object + +Represents the stateful unit of work being processed by the A2A Server for an A2A Client. A task encapsulates the entire interaction related to a specific goal or request. A task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Tasks in completed state SHOULD use artifacts for returning the generated output to the clients. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md). + +{{ render_spec_tabs('Task') }} + +### 6.2. `TaskStatus` Object + +Represents the current state and associated context (e.g., a message from the agent) of a `Task`. + +{{ render_spec_tabs('TaskStatus') }} + +### 6.3. `TaskState` Enum + +Defines the possible lifecycle states of a `Task`. + +{{ render_spec_tabs('TaskState') }} + +### 6.4. `Message` Object + +Represents a single communication turn or a piece of contextual information between a client and an agent. Messages are used for instructions, prompts, replies, and status updates. + +{{ render_spec_tabs('Message') }} + +### 6.5. `Part` Union Type + +Represents a distinct piece of content within a `Message` or `Artifact`. A `Part` is a union type representing exportable content as either `TextPart`, `FilePart`, or `DataPart`. All `Part` types also include an optional `metadata` field (`Record`) for part-specific metadata. + +{{ render_spec_tabs('Part') }} + +```ts { .no-copy } +--8<-- "types/src/types.ts:PartBase" +``` + +It **MUST** be one of the following: + +#### 6.5.1. `TextPart` Object + +For conveying plain textual content. + +```ts { .no-copy } +--8<-- "types/src/types.ts:TextPart" +``` + +#### 6.5.2. `FilePart` Object + +For conveying file-based content. + +{{ render_spec_tabs('FilePart') }} + +#### 6.5.3. `DataPart` Object + +For conveying structured JSON data. Useful for forms, parameters, or any machine-readable information. + +{{ render_spec_tabs('DataPart') }} + +### 6.6 `FileBase` Object + +Base entity for File Contents. + +```ts { .no-copy } +--8<-- "types/src/types.ts:FileBase" +``` + +#### 6.6.1 `FileWithBytes` Object + +Represents the data for a file, used within a `FilePart`. + +```ts { .no-copy } +--8<-- "types/src/types.ts:FileWithBytes" +``` + +#### 6.6.2 `FileWithUri` Object + +Represents the URI for a file, used within a `FilePart`. + +```ts { .no-copy } +--8<-- "types/src/types.ts:FileWithUri" +``` + +### 6.7. `Artifact` Object + +Represents a tangible output generated by the agent during a task. Artifacts are the results or products of the agent's work. + +{{ render_spec_tabs('Artifact') }} + +### 6.8. `PushNotificationConfig` Object + +Configuration provided by the client to the server for sending asynchronous push notifications about task updates. + +{{ render_spec_tabs('PushNotificationConfig') }} + +### 6.9. `PushNotificationAuthenticationInfo` Object + +A generic structure for specifying authentication requirements, typically used within `PushNotificationConfig` to describe how the A2A Server should authenticate to the client's webhook. + +{{ render_spec_tabs('PushNotificationAuthenticationInfo') }} + +### 6.10. `TaskPushNotificationConfig` Object + +Used as the `params` object for the [`tasks/pushNotificationConfig/set`](#76-taskspushnotificationconfigset) method and as the `result` object for the [`tasks/pushNotificationConfig/get`](#77-taskspushnotificationconfigget) method. + +{{ render_spec_tabs('TaskPushNotificationConfig') }} + +### 6.11. JSON-RPC Structures + +A2A adheres to the standard [JSON-RPC 2.0](https://www.jsonrpc.org/specification) structures for requests and responses. + +#### 6.11.1. `JSONRPCRequest` Object + +All A2A method calls are encapsulated in a JSON-RPC Request object. + +- `jsonrpc`: A String specifying the version of the JSON-RPC protocol. **MUST** be exactly `"2.0"`. +- `method`: A String containing the name of the method to be invoked (e.g., `"message/send"`, `"tasks/get"`). +- `params`: A Structured value that holds the parameter values to be used during the invocation of the method. This member **MAY** be omitted if the method expects no parameters. A2A methods typically use an `object` for `params`. +- `id`: An identifier established by the Client that **MUST** contain a String, Number, or `NULL` value if included. If it is not included it is assumed to be a notification. The value **SHOULD NOT** be `NULL` for requests expecting a response, and Numbers **SHOULD NOT** contain fractional parts. The Server **MUST** reply with the same value in the Response object if included. This member is used to correlate the context between the two objects. A2A methods typically expect a response or stream, so `id` will usually be present and non-null. + +#### 6.11.2. `JSONRPCResponse` Object + +Responses from the A2A Server are encapsulated in a JSON-RPC Response object. + +- `jsonrpc`: A String specifying the version of the JSON-RPC protocol. **MUST** be exactly `"2.0"`. +- `id`: This member is **REQUIRED**. It **MUST** be the same as the value of the `id` member in the Request Object. If there was an error in detecting the `id` in the Request object (e.g. Parse error/Invalid Request), it **MUST** be `null`. +- **EITHER** `result`: This member is **REQUIRED** on success. This member **MUST NOT** exist if there was an error invoking the method. The value of this member is determined by the method invoked on the Server. +- **OR** `error`: This member is **REQUIRED** on failure. This member **MUST NOT** exist if there was no error triggered during invocation. The value of this member **MUST** be an [`JSONRPCError`](#612-jsonrpcerror-object) object. +- The members `result` and `error` are mutually exclusive: one **MUST** be present, and the other **MUST NOT**. + +### 6.12. `JSONRPCError` Object + +When a JSON-RPC call encounters an error, the Response Object will contain an `error` member with a value of this structure. + +```ts { .no-copy } +--8<-- "types/src/types.ts:JSONRPCError" +``` + +## 7. Protocol RPC Methods + +All A2A RPC methods are invoked by the A2A Client by sending an HTTP POST request to the A2A Server's `url` (as specified in its `AgentCard`). The body of the HTTP POST request **MUST** be a `JSONRPCRequest` object, and the `Content-Type` header **MUST** be `application/json`. + +The A2A Server's HTTP response body **MUST** be a `JSONRPCResponse` object (or, for streaming methods, an SSE stream where each event's data is a `JSONRPCResponse`). The `Content-Type` for JSON-RPC responses is `application/json`. For SSE streams, it is `text/event-stream`. + +### 7.1. `message/send` + +Sends a message to an agent to initiate a new interaction or to continue an existing one. This method is suitable for synchronous request/response interactions or when client-side polling (using `tasks/get`) is acceptable for monitoring longer-running tasks. A task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Sending a message to such a task will result in an error. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md). + +
+ +=== "JSON-RPC" + - **URL:** `message/send` + - **HTTP Method:** `POST` + - **Payload**: [`MessageSendParams`](#711-messagesendparams-object) + - **Response**: [`Task` | `Message`](#61-task-object) (A message object or the current or final state of the task after processing the message). + +=== "gRPC" + - **URL:** `SendMessage` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message SendMessageRequest { + Message msg = 1; + SendMessageConfiguration configuration = 2; + } + ``` + - **Response:** + ```proto + message SendMessageResponse { + oneof payload { + Task task = 1; + Message msg = 2; + } + } + ``` + +=== "REST" + - **URL:** `/v1/message:send` + - **HTTP Method:** `POST` + - **Payload:** + ```typescript + { + message: Message, + configuration?: MessageSendConfiguration, + metadata?: { [key: string]: any } + } + ``` + - **Response:** + ```typescript + // Returns one of a message or a task + { + message?: Message, + task?: Task + } + ``` + +
+ +The `error` response for all transports in case of failure is a [`JSONRPCError`](#612-jsonrpcerror-object) or equivalent. + +#### 7.1.1. `MessageSendParams` Object + +{{ render_spec_tabs('MessageSendParams') }} + +#### 7.1.2 `MessageSendConfiguration` Object + +{{ render_spec_tabs('MessageSendConfiguration') }} + +### 7.2. `message/stream` + +Sends a message to an agent to initiate/continue a task AND subscribes the client to real-time updates for that task via Server-Sent Events (SSE). This method requires the server to have `AgentCard.capabilities.streaming: true`. Just like `message/send`, a task which has reached a terminal state (completed, canceled, rejected, or failed) can't be restarted. Sending a message to such a task will result in an error. For more information, refer to the [Life of a Task guide](./topics/life-of-a-task.md). + +
+ +=== "JSON-RPC" + - **URL:** `message/stream` + - **HTTP Method:** `POST` + - **Payload**: [`MessageSendParams`](#711-messagesendparams-object) (same as `message/send`) + - **Response**: A stream of Server-Sent Events. Each SSE `data` field contains a [`SendStreamingMessageResponse`](#721-sendstreamingmessageresponse-object) + +=== "gRPC" + - **URL:** `SendStreamingMessage` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message SendMessageRequest { + Message msg = 1; + SendMessageConfiguration configuration = 2; + } + ``` + - **Response:** + ```proto + message StreamResponse { + oneof payload { + Task task; + Message msg; + TaskStatusUpdateEvent status_update; + TaskArtifactUpdateEvent artifact_update; + } + } + ``` + +=== "REST" + - **URL:** `/v1/message:stream` + - **HTTP Method:** `POST` + - **Payload:** + ```typescript + { + message: Message, + configuration?: MessageSendConfiguration, + metadata?: { [key: string]: any } + } + ``` + - **Response:** + ```typescript + { + message?: Message + task?: Task + statusUpdate?: TaskStatusUpdateEvent + artifactUpdate?: TaskArtifactUpdateEvent + } + ``` + +
+ +#### 7.2.1. `SendStreamingMessageResponse` Object + +This is the structure of the JSON object found in the `data` field of each Server-Sent Event sent by the server for a `message/stream` request or `tasks/resubscribe` request. + +```ts { .no-copy } +--8<-- "types/src/types.ts:SendStreamingMessageResponse" +``` + +{{ render_spec_tabs('SendStreamingMessageSuccessResponse') }} + +#### 7.2.2. `TaskStatusUpdateEvent` Object + +Carries information about a change in the task's status during streaming. This is one of the possible `result` types in a `SendStreamingMessageSuccessResponse`. + +{{ render_spec_tabs('TaskStatusUpdateEvent') }} + +#### 7.2.3. `TaskArtifactUpdateEvent` Object + +Carries a new or updated artifact (or a chunk of an artifact) generated by the task during streaming. This is one of the possible `result` types in a `SendTaskStreamingResponse`. + +{{ render_spec_tabs('TaskArtifactUpdateEvent') }} + +### 7.3. `tasks/get` + +Retrieves the current state (including status, artifacts, and optionally history) of a previously initiated task. This is typically used for polling the status of a task initiated with `message/send`, or for fetching the final state of a task after being notified via a push notification or after an SSE stream has ended. + +
+ +=== "JSON-RPC" + - **URL:** `tasks/get` + - **HTTP Method:** `POST` + - **Payload**: [`TaskQueryParams`](#731-taskqueryparams-object) + - **Response**: `Task` + +=== "gRPC" + - **URL:** `GetTask` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message GetTaskRequest { + // name=tasks/{id} + string name; + int32 history_length; + } + ``` + - **Response**: `Task` + +=== "REST" + - **URL:** `v1/tasks/{id}?historyLength={historyLength}` + - **HTTP Method:** `GET` + - **Payload:** None + - **Response**: `Task` + +
+ +#### 7.3.1. `TaskQueryParams` Object + +{{ render_spec_tabs('TaskQueryParams') }} + +### 7.4. `tasks/list` + +Retrieves a list of tasks with optional filtering and pagination capabilities. This method allows clients to discover and manage multiple tasks across different contexts or with specific status criteria. + +**Pagination Strategy:** This method uses cursor-based pagination (via `pageToken`/`nextPageToken`) rather than offset-based pagination for better performance and consistency, especially with large datasets. Cursor-based pagination avoids the "deep pagination problem" where skipping large numbers of records becomes inefficient for databases. This approach is consistent with the gRPC specification, which also uses cursor-based pagination (`page_token`/`next_page_token`). + +**Ordering:** Implementations **MUST** return tasks sorted by their last update time in descending order (most recently updated tasks first). This ensures consistent pagination and allows clients to efficiently monitor recent task activity. + +**Security Note:** Implementations **MUST** ensure appropriate scope limitation based on the authenticated user's permissions. Servers **SHOULD NOT** return tasks from other users or unauthorized contexts. Even when `contextId` is not specified in the request, the implementation **MUST** still scope results to the caller's authorization and tenancy boundaries. The implementation **MAY** choose to limit results to tasks created by the current authenticated user, tasks within a default user context, or return an authorization error if the scope cannot be safely determined. + +- **Request `params` type**: [`ListTasksParams`](#741-listtasksparams-object) (Optional parameters for filtering and pagination) +- **Response `result` type (on success)**: [`ListTasksResult`](#742-listtasksresult-object) (A paginated list of tasks matching the criteria) +- **Response `error` type (on failure)**: [`JSONRPCError`](#612-jsonrpcerror-object) (see specific error cases below) + +**Error Cases for `tasks/list`:** + +The following table details specific error conditions that should result in an `InvalidParamsError` (-32602) response: + +| Parameter | Invalid Condition | Error Details | Example | +|-----------|------------------|---------------|---------| +| `pageSize` | Value outside 1–100 range | Must be between 1 and 100 inclusive | `pageSize: 0` or `pageSize: 101` | +| `pageToken` | Malformed token format | Token is not a valid base64-encoded cursor | `pageToken: "invalid!@#"` | +| `pageToken` | Expired token | Token has exceeded its validity period | `pageToken: ""` | +| `historyLength` | Negative value | Must be non-negative integer | `historyLength: -1` | +| `status` | Invalid enum value | Must be one of: `pending`, `working`, `completed`, `failed`, `canceled` | `status: "running"` | +| `lastUpdatedAfter` | Invalid timestamp format | Must be a valid Unix timestamp in milliseconds | `lastUpdatedAfter: "not-a-number"` | +| `lastUpdatedAfter` | Future timestamp | Timestamp is in the future (optional validation) | `lastUpdatedAfter: 4102444800000` (year 2100) | + +**Additional Error Responses:** + +- **`-32001` (`TaskNotFoundError`)**: When `contextId` refers to a nonexistent or inaccessible context +- **`-32600` (`InvalidRequest`)**: When the request structure is malformed +- **`-32603` (`InternalError`)**: When a server-side error occurs during task retrieval + +#### 7.4.1. `ListTasksParams` Object + +Parameters for filtering and paginating task results. + +```ts { .no-copy } +--8<-- "types/src/types.ts:ListTasksParams" +``` + +**Note on `includeArtifacts` parameter:** When `includeArtifacts` is `false` (the default), the `artifacts` field **MUST** be omitted entirely from each `Task` object in the response. The field should not be present as an empty array or null value. When `includeArtifacts` is `true`, the `artifacts` field should be included with its actual content (which may be an empty array if the task has no artifacts). + +#### 7.4.2. `ListTasksResult` Object + +Result object containing the filtered tasks and pagination information. + +```ts { .no-copy } +--8<-- "types/src/types.ts:ListTasksResult" +``` + +**Note on `nextPageToken`:** The `nextPageToken` field **MUST** always be present in the response. When there are no more results to retrieve (i.e., this is the final page), the field **MUST** be set to an empty string (`""`). Clients should check for an empty string to determine if more pages are available. + +### 7.5. `tasks/cancel` + +Requests the cancellation of an ongoing task. The server will attempt to cancel the task, but success is not guaranteed (e.g., the task might have already completed or failed, or cancellation might not be supported at its current stage). + +
+ +=== "JSON-RPC" + - **URL:** `tasks/cancel` + - **HTTP Method:** `POST` + - **Payload**: [`TaskIdParams`](#751-taskidparams-object-for-taskscancel-and-taskspushnotificationconfigget) + - **Response**: [`Task`](#61-task-object) + +=== "gRPC" + - **URL:** `CancelTask` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message CancelTaskRequest{ + // name=tasks/{id} + string name; + } + ``` + - **Response**: [`Task`](#61-task-object) + +=== "REST" + - **URL:** `/v1/tasks/{id}:cancel` + - **HTTP Method:** `POST` + - **Payload:** + ```typescript + { + name: string + } + ``` + - **Response**: [`Task`](#61-task-object) + +
+ +- **Response `error` type (on failure)**: [`JSONRPCError`](#612-jsonrpcerror-object) (e.g., [`TaskNotFoundError`](#82-a2a-specific-errors), [`TaskNotCancelableError`](#82-a2a-specific-errors)). + +#### 7.5.1. `TaskIdParams` Object (for `tasks/cancel` and `tasks/pushNotificationConfig/get`) + +A simple object containing just the task ID and optional metadata. + +{{ render_spec_tabs('TaskIdParams') }} + +### 7.6. `tasks/pushNotificationConfig/set` + +Sets or updates the push notification configuration for a specified task. This allows the client to tell the server where and how to send asynchronous updates for the task. Requires the server to have `AgentCard.capabilities.pushNotifications: true`. + +
+ +=== "JSON-RPC" + - **URL:** `tasks/pushNotificationConfig/set` + - **HTTP Method:** `POST` + - **Payload**: [`TaskPushNotificationConfig`](#610-taskpushnotificationconfig-object) + - **Response**: [`TaskPushNotificationConfig`](#610-taskpushnotificationconfig-object) + +=== "gRPC" + - **URL:** `CreateTaskPushNotification` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message SetTaskPushNotificationRequest { + TaskPushNotificationConfig config = 1; + } + ``` + - **Response**: `TaskPushNotificationConfig` + +=== "REST" + - **URL:** `/v1/tasks/{id}/pushNotificationConfigs` + - **HTTP Method:** `POST` + - **Payload:** + ```typescript + { + config: TaskPushNotificationConfig + } + ``` + - **Response**: `TaskPushNotificationConfig` + +
+ +### 7.7. `tasks/pushNotificationConfig/get` + +Retrieves the current push notification configuration for a specified task. Requires the server to have `AgentCard.capabilities.pushNotifications: true`. + +
+ +=== "JSON-RPC" + - **URL:** `tasks/pushNotificationConfig/get` + - **HTTP Method:** `POST` + - **Payload**: [`GetTaskPushNotificationConfigParams`](#771-gettaskpushnotificationconfigparams-object-taskspushnotificationconfigget) + - **Response**: [`TaskPushNotificationConfig`](#610-taskpushnotificationconfig-object) + +=== "gRPC" + - **URL:** `GetTaskPushNotification` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message TaskSubscriptionRequest { + // name=tasks/{id}/pushNotification/{id} + string name; + } + ``` + - **Response**: `TaskPushNotificationConfig` + +=== "REST" + - **URL:** `/v1/tasks/{taskId}/pushNotificationConfigs/{configId}` + - **HTTP Method:** `GET` + - **Payload:** None + - **Response**: `TaskPushNotificationConfig` + +
+ +**Response `error` type (on failure)**: [`JSONRPCError`](#612-jsonrpcerror-object) (e.g., [`PushNotificationNotSupportedError`](#82-a2a-specific-errors), [`TaskNotFoundError`](#82-a2a-specific-errors)). + +#### 7.7.1. `GetTaskPushNotificationConfigParams` Object (`tasks/pushNotificationConfig/get`) + +A object for fetching the push notification configuration for a task. + +{{ render_spec_tabs('GetTaskPushNotificationConfigParams') }} + +### 7.8. `tasks/pushNotificationConfig/list` + +Retrieves the associated push notification configurations for a specified task. Requires the server to have `AgentCard.capabilities.pushNotifications: true`. + +
+ +=== "JSON-RPC" + - **URL:** `tasks/pushNotificationConfig/list` + - **HTTP Method:** `POST` + - **Payload:** [`ListTaskPushNotificationConfigParams`](#781-listtaskpushnotificationconfigparams-object-taskspushnotificationconfiglist) + - **Response**: `TaskPushNotificationConfig[]` + +=== "gRPC" + - **URL:** `ListTaskPushNotification` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message ListTaskPushNotificationRequest { + // parent=tasks/{id} + string parent = 1; + } + ``` + - **Response**: `repeated TaskPushNotificationConfig` + +=== "REST" + - **URL:** `/v1/tasks/{id}/pushNotificationConfigs` + - **HTTP Method:** `GET` + - **Payload:**: None + - **Response**: `[TaskPushNotificationConfig]` + +
+ +- **Response `error` type (on failure)**: [`JSONRPCError`](#612-jsonrpcerror-object) (e.g., [`PushNotificationNotSupportedError`](#82-a2a-specific-errors), [`TaskNotFoundError`](#82-a2a-specific-errors)). + +#### 7.8.1. `ListTaskPushNotificationConfigParams` Object (`tasks/pushNotificationConfig/list`) + +A object for fetching the push notification configurations for a task. + +{{ render_spec_tabs('ListTaskPushNotificationConfigParams') }} + +### 7.9. `tasks/pushNotificationConfig/delete` + +Deletes an associated push notification configuration for a task. Requires the server to have `AgentCard.capabilities.pushNotifications: true`. + +- **Request `params` type**: [`DeleteTaskPushNotificationConfigParams`](#791-deletetaskpushnotificationconfigparams-object-taskspushnotificationconfigdelete) +- **Response `result` type (on success)**: [`null`] +- **Response `error` type (on failure)**: [`JSONRPCError`](#612-jsonrpcerror-object) (e.g., [`PushNotificationNotSupportedError`](#82-a2a-specific-errors), [`TaskNotFoundError`](#82-a2a-specific-errors)). + +#### 7.9.1. `DeleteTaskPushNotificationConfigParams` Object (`tasks/pushNotificationConfig/delete`) + +A object for deleting an associated push notification configuration for a task. + +{{ render_spec_tabs('DeleteTaskPushNotificationConfigParams') }} + +### 7.10. `tasks/resubscribe` + +Allows a client to reconnect to an SSE stream for an ongoing task after a previous connection (from `message/stream` or an earlier `tasks/resubscribe`) was interrupted. Requires the server to have `AgentCard.capabilities.streaming: true`. + +The purpose is to resume receiving _subsequent_ updates. The server's behavior regarding events missed during the disconnection period (e.g., whether it attempts to backfill some missed events or only sends new ones from the point of resubscription) is implementation-dependent and not strictly defined by this specification. + +
+ +=== "JSON-RPC" + - **URL:** `tasks/resubscribe` + - **HTTP Method:** `POST` + - **Payload**: [`TaskIdParams`](#751-taskidparams-object-for-taskscancel-and-taskspushnotificationconfigget) + - **Response**: A stream of Server-Sent Events. Each SSE `data` field contains a [`SendStreamingMessageResponse`](#721-sendstreamingmessageresponse-object) + +=== "gRPC" + - **URL:** `TaskSubscription` + - **HTTP Method:** `POST` + - **Payload:** + ```proto + message TaskSubscriptionRequest{ + // name=tasks/{id} + string name; + } + ``` + - **Response:** + ```proto + message StreamResponse { + oneof payload { + Task task; + Message msg; + TaskStatusUpdateEvent status_update; + TaskArtifactUpdateEvent artifact_update; + } + } + ``` + +=== "REST" + - **URL:** `/v1/tasks/{id}:subscribe` + - **HTTP Method:** `POST` + - **Payload:** + ```typescript + { + name: string + } + ``` + - **Response:** + ```typescript + { + message?: Message + task?: Task + statusUpdate?: TaskStatusUpdateEvent + artifactUpdate?: TaskArtifactUpdateEvent + } + ``` + +
+ +### 7.10. `agent/getAuthenticatedExtendedCard` + +Retrieves a potentially more detailed version of the Agent Card after the client has authenticated. This endpoint is available only if `AgentCard.supportsAuthenticatedExtendedCard` is `true`. + +- **Authentication**: The client **MUST** authenticate the request using one of the schemes declared in the public `AgentCard.securitySchemes` and `AgentCard.security` fields. +- **Response `result` type (on success)**: `AgentCard` (A complete Agent Card object, which may contain additional details or skills not present in the public card). +- **Response `error` type (on failure)**: Standard HTTP error codes. + - `401 Unauthorized`: Authentication failed (missing or invalid credentials). The server **SHOULD** include a `WWW-Authenticate` header. + +
+ +=== "JSON-RPC" + - **URL:** `agent/getAuthenticatedExtendedCard` + - **HTTP Method:** `POST` + - **Payload:** None + - **Response:** `AgentCard` + +=== "gRPC" + - **URL:** `GetAgentCard` + - **HTTP Method:** `POST` + - **Payload:** None + - **Response:** `AgentCard` + +=== "REST" + - **URL:** `/v1/card` + - **HTTP Method:** `GET` + - **Payload:** None + - **Response:** `AgentCard` + +
+ +Clients retrieving this authenticated card **SHOULD** replace their cached public Agent Card with the content received from this endpoint for the duration of their authenticated session or until the card's version changes. + +```ts { .no-copy } +--8<-- "types/src/types.ts:GetAuthenticatedExtendedCardSuccessResponse" +``` + +## 8. Error Handling + +A2A uses standard [JSON-RPC 2.0 error codes and structure](https://www.jsonrpc.org/specification#error_object) for reporting errors. Errors are returned in the `error` member of the `JSONRPCErrorResponse` object. See [`JSONRPCError` Object definition](#612-jsonrpcerror-object). + +### 8.1. Standard JSON-RPC Errors + +These are standard codes defined by the JSON-RPC 2.0 specification. + +| Code | JSON-RPC Spec Meaning | Typical A2A `message` | Description | +| :------------------- | :-------------------- | :------------------------ | :------------------------------------------------------------------------------------------- | +| `-32700` | Parse error | Invalid JSON payload | Server received JSON that was not well-formed. | +| `-32600` | Invalid Request | Invalid JSON-RPC Request | The JSON payload was valid JSON, but not a valid JSON-RPC Request object. | +| `-32601` | Method not found | Method not found | The requested A2A RPC `method` (e.g., `"tasks/foo"`) does not exist or is not supported. | +| `-32602` | Invalid params | Invalid method parameters | The `params` provided for the method are invalid (e.g., wrong type, missing required field). | +| `-32603` | Internal error | Internal server error | An unexpected error occurred on the server during processing. | +| `-32000` to `-32099` | Server error | _(Server-defined)_ | Reserved for implementation-defined server-errors. A2A-specific errors use this range. | + +### 8.2. A2A-Specific Errors + +These are custom error codes defined within the JSON-RPC server error range (`-32000` to `-32099`) to provide more specific feedback about A2A-related issues. Servers **SHOULD** use these codes where applicable. + +| Code | Error Name (Conceptual) | Typical `message` string | Description | +| :------- | :---------------------------------- | :--------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `-32001` | `TaskNotFoundError` | Task not found | The specified task `id` does not correspond to an existing or active task. It might be invalid, expired, or already completed and purged. | +| `-32002` | `TaskNotCancelableError` | Task cannot be canceled | An attempt was made to cancel a task that is not in a cancelable state (e.g., it has already reached a terminal state like `completed`, `failed`, or `canceled`). | +| `-32003` | `PushNotificationNotSupportedError` | Push Notification is not supported | Client attempted to use push notification features (e.g., `tasks/pushNotificationConfig/set`) but the server agent does not support them (i.e., `AgentCard.capabilities.pushNotifications` is `false`). | +| `-32004` | `UnsupportedOperationError` | This operation is not supported | The requested operation or a specific aspect of it (perhaps implied by parameters) is not supported by this server agent implementation. Broader than just method not found. | +| `-32005` | `ContentTypeNotSupportedError` | Incompatible content types | A [Media Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) provided in the request's `message.parts` (or implied for an artifact) is not supported by the agent or the specific skill being invoked. | +| `-32006` | `InvalidAgentResponseError` | Invalid agent response type | Agent generated an invalid response for the requested method | +| `-32007` | `AuthenticatedExtendedCardNotConfiguredError` | Authenticated Extended Card not configured | The agent does not have an Authenticated Extended Card configured.| + +Servers MAY define additional error codes within the `-32000` to `-32099` range for more specific scenarios not covered above, but they **SHOULD** document these clearly. The `data` field of the `JSONRPCError` object can be used to provide more structured details for any error. + +## 9. Common Workflows & Examples + +This section provides illustrative JSON examples of common A2A interactions. Timestamps, context IDs, and request/response IDs are for demonstration purposes. For brevity, some optional fields might be omitted if not central to the example. + +### 9.1. Fetching Authenticated Extended Agent Card + +**Scenario:** A client discovers a public Agent Card indicating support for an authenticated extended card and wants to retrieve the full details. + +1. **Client fetches the public Agent Card:** + + ```none + GET https://example.com/.well-known/agent-card.json + ``` + + _Server responds with the public Agent Card (like the example in Section 5.6), including `supportsAuthenticatedExtendedCard: true` (at the root level) and `securitySchemes`._ + +2. **Client identifies required authentication from the public card.** + +3. **Client obtains necessary credentials out-of-band (e.g., performs OAuth 2.0 flow with Google, resulting in an access token).** + +4. **Client fetches the authenticated extended Agent Card using `agent/getAuthenticatedExtendedCard` request:** + + ```json + { + "jsonrpc": "2.0", + "id": 1, + "method": "agent/getAuthenticatedExtendedCard" + } + ``` + +5. **Server authenticates and authorizes the request.** + +6. **Server responds with the full Agent Card as the JSON-RPC result:** + +### 9.2. Basic Execution (Synchronous / Polling Style) + +**Scenario:** Client asks a simple question, and the agent responds quickly with a task + +1. **Client sends a message using `message/send`:** + + ```json + { + "jsonrpc": "2.0", + "id": 1, + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "9229e770-767c-417b-a0b0-f0741243c589" + }, + "metadata": {} + } + } + ``` + +2. **Server processes the request, creates a task and responds (task completes quickly)** + + ```json + { + "jsonrpc": "2.0", + "id": 1, + "result": { + "id": "363422be-b0f9-4692-a24d-278670e7c7f1", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed" + }, + "artifacts": [ + { + "artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1", + "name": "joke", + "parts": [ + { + "kind": "text", + "text": "Why did the chicken cross the road? To get to the other side!" + } + ] + } + ], + "history": [ + { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "9229e770-767c-417b-a0b0-f0741243c589", + "taskId": "363422be-b0f9-4692-a24d-278670e7c7f1", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4" + } + ], + "kind": "task", + "metadata": {} + } + } + ``` + +_If the task were longer-running, the server might initially respond with `status.state: "working"`. The client would then periodically call `tasks/get` with params: `{"id": "363422be-b0f9-4692-a24d-278670e7c7f1"}` until the task reaches a terminal state._ + +**Scenario:** Client asks a simple question, and the agent responds quickly without a task + +1. **Client sends a message using `message/send`:** + + ```json + { + "jsonrpc": "2.0", + "id": 1, + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "tell me a joke" + } + ], + "messageId": "9229e770-767c-417b-a0b0-f0741243c589" + }, + "metadata": {} + } + } + ``` + +2. **Server processes the request, responds quickly without a task** + + ```json + { + "jsonrpc": "2.0", + "id": 1, + "result": { + "messageId": "363422be-b0f9-4692-a24d-278670e7c7f1", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "parts": [ + { + "kind": "text", + "text": "Why did the chicken cross the road? To get to the other side!" + } + ], + "kind": "message", + "metadata": {} + } + } + ``` + +### 9.3. Streaming Task Execution (SSE) + +**Scenario:** Client asks the agent to write a long paper describing an attached picture. + +1. **Client sends a message and subscribes using `message/stream`:** + + ```json + { + "jsonrpc": "2.0", + "id": 1, + "method": "message/stream", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "write a long paper describing the attached pictures" + }, + { + "kind": "file", + "file": { + "mimeType": "image/png", + "data": "" + } + } + ], + "messageId": "bbb7dee1-cf5c-4683-8a6f-4114529da5eb" + }, + "metadata": {} + } + } + ``` + +2. **Server responds with HTTP 200 OK, `Content-Type: text/event-stream`, and starts sending SSE events:** + + _Event 1: Task status update - working_ + + ```json + data: { + "jsonrpc": "2.0", + "id": 1, + "result": { + "id": "225d6247-06ba-4cda-a08b-33ae35c8dcfa", + "contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1", + "status": { + "state": "submitted", + "timestamp":"2025-04-02T16:59:25.331844" + }, + "history": [ + { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "write a long paper describing the attached pictures" + }, + { + "kind": "file", + "file": { + "mimeType": "image/png", + "data": "" + } + } + ], + "messageId": "bbb7dee1-cf5c-4683-8a6f-4114529da5eb", + "taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa", + "contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1" + } + ], + "kind": "task", + "metadata": {} + } + } + + data: { + "jsonrpc": "2.0", + "id": 1, + "result": { + "taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa", + "contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1", + "artifact": { + "artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1", + "parts": [ + {"kind":"text", "text": "
"} + ] + }, + "append": false, + "lastChunk": false, + "kind":"artifact-update" + } + } + + data: { + "jsonrpc": "2.0", + "id": 1, + "result": { + "taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa", + "contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1", + "artifact": { + "artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1", + "parts": [ + {"kind":"text", "text": "
"} + ], + }, + "append": true, + "lastChunk": false, + "kind":"artifact-update" + } + } + + + data: { + "jsonrpc": "2.0", + "id": 1, + "result": { + "taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa", + "contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1", + "artifact": { + "artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1", + "parts": [ + {"kind":"text", "text": "
"} + ] + }, + "append": true, + "lastChunk": true, + "kind":"artifact-update" + } + } + + data: { + "jsonrpc": "2.0", + "id": 1, + "result": { + "taskId": "225d6247-06ba-4cda-a08b-33ae35c8dcfa", + "contextId": "05217e44-7e9f-473e-ab4f-2c2dde50a2b1", + "status": { + "state": "completed", + "timestamp":"2025-04-02T16:59:35.331844" + }, + "final": true, + "kind":"status-update" + } + } + ``` + + _(Server closes the SSE connection after the `final:true` event)._ + +### 9.4. Multi-Turn Interaction (Input Required) + +**Scenario:** Client wants to book a flight, and the agent needs more information. + +1. **Client sends a message using `message/send`:** + + ```json + { + "jsonrpc": "2.0", + "id": "req-003", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [{ "kind": "text", "text": "I'd like to book a flight." }] + }, + "messageId": "c53ba666-3f97-433c-a87b-6084276babe2" + } + } + ``` + +2. **Server responds, task state is `input-required`:** + + ```json + { + "jsonrpc": "2.0", + "id": "req-003", + "result": { + "id": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "input-required", + "message": { + "role": "agent", + "parts": [ + { + "kind": "text", + "text": "Sure, I can help with that! Where would you like to fly to, and from where? Also, what are your preferred travel dates?" + } + ], + "messageId": "c2e1b2dd-f200-4b04-bc22-1b0c65a1aad2", + "taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4" + }, + "timestamp": "2024-03-15T10:10:00Z" + }, + "history": [ + { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "I'd like to book a flight." + } + ], + "messageId": "c53ba666-3f97-433c-a87b-6084276babe2", + "taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4" + } + ], + "kind": "task" + } + } + ``` + +3. **Client `message/send` (providing the requested input, using the _same_ task ID):** + + ```json + { + "jsonrpc": "2.0", + "id": "req-004", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "I want to fly from New York (JFK) to London (LHR) around October 10th, returning October 17th." + } + ], + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "messageId": "0db1d6c4-3976-40ed-b9b8-0043ea7a03d3" + }, + "configuration": { + "blocking": true + } + } + } + ``` + +4. **Server processes the new input and responds (e.g., task completed or more input needed):** + + ```json + { + "jsonrpc": "2.0", + "id": "req-004", + "result": { + "id": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed", + "message": { + "role": "agent", + "parts": [ + { + "kind": "text", + "text": "Okay, I've found a flight for you. Confirmation XYZ123. Details are in the artifact." + } + ] + } + }, + "artifacts": [ + { + "artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1", + "name": "FlightItinerary.json", + "parts": [ + { + "kind": "data", + "data": { + "confirmationId": "XYZ123", + "from": "JFK", + "to": "LHR", + "departure": "2024-10-10T18:00:00Z", + "arrival": "2024-10-11T06:00:00Z", + "returnDeparture": "..." + } + } + ] + } + ], + "history": [ + { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "I'd like to book a flight." + } + ], + "messageId": "c53ba666-3f97-433c-a87b-6084276babe2", + "taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4" + }, + { + "role": "agent", + "parts": [ + { + "kind": "text", + "text": "Sure, I can help with that! Where would you like to fly to, and from where? Also, what are your preferred travel dates?" + } + ], + "messageId": "c2e1b2dd-f200-4b04-bc22-1b0c65a1aad2", + "taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4" + }, + { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "I want to fly from New York (JFK) to London (LHR) around October 10th, returning October 17th." + } + ], + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "taskId": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "messageId": "0db1d6c4-3976-40ed-b9b8-0043ea7a03d3" + } + ], + "kind": "task", + "metadata": {} + } + } + ``` + +### 9.5. Task Listing and Management + +**Scenario:** Client wants to see all tasks from a specific context or all tasks with a particular status. + +1. **Client requests all tasks from a specific context:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-001", + "method": "tasks/list", + "params": { + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "pageSize": 10, + "historyLength": 3 + } + } + ``` + +2. **Server responds with matching tasks:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-001", + "result": { + "tasks": [ + { + "id": "3f36680c-7f37-4a5f-945e-d78981fafd36", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed", + "timestamp": "2024-03-15T10:15:00Z" + }, + "totalSize": 5, + "pageSize": 10, + "nextPageToken": "" + } + } + ``` + +3. **Client requests all working tasks across all contexts:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-002", + "method": "tasks/list", + "params": { + "status": "working", + "pageSize": 20 + } + } + ``` + +4. **Server responds with all currently working tasks:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-002", + "result": { + "tasks": [ + { + "id": "789abc-def0-1234-5678-9abcdef01234", + "contextId": "another-context-id", + "status": { + "state": "working", + "message": { + "role": "agent", + "parts": [ + { + "kind": "text", + "text": "Processing your document analysis..." + } + ], + "messageId": "msg-status-update" + }, + "timestamp": "2024-03-15T10:20:00Z" + }, + "kind": "task" + } + ], + "totalSize": 1, + "pageSize": 20, + "nextPageToken": "" + } + } + ``` + +5. **Continuing pagination - Client requests the next page using nextPageToken:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-003", + "method": "tasks/list", + "params": { + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "pageSize": 10, + "pageToken": "" + } + } + ``` + +6. **Server responds with the next page of results:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-003", + "result": { + "tasks": [ + // ... additional tasks + ], + "totalSize": 15, + "pageSize": 10, + "nextPageToken": "" + } + } + ``` + +7. **Error example - Client sends invalid parameters:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-error-001", + "method": "tasks/list", + "params": { + "pageSize": 150, + "historyLength": -5, + "status": "running" + } + } + ``` + +8. **Server responds with validation error:** + + ```json + { + "jsonrpc": "2.0", + "id": "list-error-001", + "error": { + "code": -32602, + "message": "Invalid params", + "data": { + "errors": [ + { + "field": "pageSize", + "message": "Must be between 1 and 100 inclusive, got 150" + }, + { + "field": "historyLength", + "message": "Must be non-negative integer, got -5" + }, + { + "field": "status", + "message": "Invalid status value 'running'. Must be one of: pending, working, completed, failed, canceled" + } + ] + } + } + } + ``` + +### 9.6. Push Notification Setup and Usage + +**Scenario:** Client requests a long-running report generation and wants to be notified via webhook when it's done. + +1. **Client `message/send` with `pushNotification` config:** + + ```json + { + "jsonrpc": "2.0", + "id": "req-005", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "Generate the Q1 sales report. This usually takes a while. Notify me when it's ready." + } + ], + "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6" + }, + "configuration": { + "pushNotificationConfig": { + "url": "https://client.example.com/webhook/a2a-notifications", + "token": "secure-client-token-for-task-aaa", + "authentication": { + "schemes": ["Bearer"] + // Assuming server knows how to get a Bearer token for this webhook audience, + // or this implies the webhook is public/uses the 'token' for auth. + // 'credentials' could provide more specifics if needed by the server. + } + } + } + } + } + ``` + +2. **Server acknowledges the task (e.g., status `submitted` or `working`):** + + ```json + { + "jsonrpc": "2.0", + "id": "req-005", + "result": { + "id": "43667960-d455-4453-b0cf-1bae4955270d", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { "state": "submitted", "timestamp": "2024-03-15T11:00:00Z" } + // ... other fields ... + } + } + ``` + +3. **(Later) A2A Server completes the task and POSTs a notification to `https://client.example.com/webhook/a2a-notifications`:** + + - **HTTP Headers might include:** + - `Authorization: Bearer ` (if server authenticates to webhook) + - `Content-Type: application/json` + - `X-A2A-Notification-Token: secure-client-token-for-task-aaa` + - **HTTP Body (Task object is sent as JSON payload):** + + ```json + { + "id": "43667960-d455-4453-b0cf-1bae4955270d", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { "state": "completed", "timestamp": "2024-03-15T18:30:00Z" }, + "kind": "task" + // ... other fields ... + } + ``` + +4. **Client's Webhook Service:** + + - Receives the POST. + - Validates the `Authorization` header (if applicable). + - Validates the `X-A2A-Notification-Token`. + - Internally processes the notification (e.g., updates application state, notifies end user). + +### 9.7. File Exchange (Upload and Download) + +**Scenario:** Client sends an image for analysis, and the agent returns a modified image. + +1. **Client `message/send` with a `FilePart` (uploading image bytes):** + + ```json + { + "jsonrpc": "2.0", + "id": "req-007", + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "Analyze this image and highlight any faces." + }, + { + "kind": "file", + "file": { + "name": "input_image.png", + "mimeType": "image/png", + "bytes": "iVBORw0KGgoAAAANSUhEUgAAAAUA..." // Base64 encoded image data + } + } + ], + "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6" + } + } + } + ``` + +2. **Server processes the image and responds with a `FilePart` in an artifact (e.g., providing a URI to the modified image):** + + ```json + { + "jsonrpc": "2.0", + "id": "req-007", + "result": { + "id": "43667960-d455-4453-b0cf-1bae4955270d", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { "state": "completed", "timestamp": "2024-03-15T12:05:00Z" }, + "artifacts": [ + { + "artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1", + "name": "processed_image_with_faces.png", + "parts": [ + { + "kind": "file", + "file": { + "name": "output.png", + "mimeType": "image/png", + // Server might provide a URI to a temporary storage location + "uri": "https://storage.example.com/processed/task-bbb/output.png?token=xyz" + // Or, alternatively, it could return bytes directly: + // "bytes": "ASEDGhw0KGgoAAAANSUhEUgAA..." + } + } + ] + } + ], + "kind": "task" + } + } + ``` + +### 9.8. Structured Data Exchange (Requesting and Providing JSON) + +**Scenario:** Client asks for a list of open support tickets in a specific JSON format. + +1. **Client `message/send`, `Part.metadata` hints at desired output schema/Media Type:** + _(Note: A2A doesn't formally standardize schema negotiation in v0.2.0, but `metadata` can be used for such hints by convention between client/server)._ + + ```json + { + "jsonrpc": "2.0", + "id": 9, + "method": "message/send", + "params": { + "message": { + "role": "user", + "parts": [ + { + "kind": "text", + "text": "Show me a list of my open IT tickets", + "metadata": { + "mimeType": "application/json", + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ticketNumber": { "type": "string" }, + "description": { "type": "string" } + } + } + } + } + } + ], + "messageId": "85b26db5-ffbb-4278-a5da-a7b09dea1b47" + }, + "metadata": {} + } + } + ``` + +2. **Server responds with structured JSON data:** + + ```json + { + "jsonrpc": "2.0", + "id": 9, + "result": { + "id": "d8c6243f-5f7a-4f6f-821d-957ce51e856c", + "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", + "status": { + "state": "completed", + "timestamp": "2025-04-17T17:47:09.680794" + }, + "artifacts": [ + { + "artifactId": "c5e0382f-b57f-4da7-87d8-b85171fad17c", + "parts": [ + { + "kind": "text", + "text": "[{\"ticketNumber\":\"REQ12312\",\"description\":\"request for VPN access\"},{\"ticketNumber\":\"REQ23422\",\"description\":\"Add to DL - team-gcp-onboarding\"}]" + } + ] + } + ], + "kind": "task" + } + } + ``` + +These examples illustrate the flexibility of A2A in handling various interaction patterns and data types. Implementers should refer to the detailed object definitions for all fields and constraints. + +## 10. Appendices + +### 10.1. Relationship to MCP (Model Context Protocol) + +A2A and MCP are complementary protocols designed for different aspects of agentic systems: + +- **[Model Context Protocol (MCP)](https://modelcontextprotocol.io/):** Focuses on standardizing how AI models and agents connect to and interact with **tools, APIs, data sources, and other external resources.** It defines structured ways to describe tool capabilities (like function calling in LLMs), pass inputs, and receive structured outputs. Think of MCP as the "how-to" for an agent to _use_ a specific capability or access a resource. +- **Agent2Agent Protocol (A2A):** Focuses on standardizing how independent, often opaque, **AI agents communicate and collaborate with each other as peers.** A2A provides an application-level protocol for agents to discover each other, negotiate interaction modalities, manage shared tasks, and exchange conversational context or complex results. It's about how agents _partner_ or _delegate_ work. + +**How they work together:** +An A2A Client agent might request an A2A Server agent to perform a complex task. The Server agent, in turn, might use MCP to interact with several underlying tools, APIs, or data sources to gather information or perform actions necessary to fulfill the A2A task. + +For a more detailed comparison, see the [A2A and MCP guide](./topics/a2a-and-mcp.md). + +### 10.2. Security Considerations Summary + +Security is a paramount concern in A2A. Key considerations include: + +- **Transport Security:** Always use HTTPS with strong TLS configurations in production environments. +- **Authentication:** + - Handled via standard HTTP mechanisms (e.g., `Authorization` header with Bearer tokens, API keys). + - Requirements are declared in the `AgentCard`. + - Credentials MUST be obtained out-of-band by the client. + - A2A Servers MUST authenticate every request. +- **Authorization:** + - A server-side responsibility based on the authenticated identity. + - Implement the principle of least privilege. + - Can be granular, based on skills, actions, or data. +- **Push Notification Security:** + - Webhook URL validation (by the A2A Server sending notifications) is crucial to prevent SSRF. + - Authentication of the A2A Server to the client's webhook is essential. + - Authentication of the notification by the client's webhook receiver (verifying it came from the legitimate A2A Server and is relevant) is critical. + - See the [Streaming & Asynchronous Operations guide](./topics/streaming-and-async.md#security-considerations-for-push-notifications) for detailed push notification security. +- **Input Validation:** Servers MUST rigorously validate all RPC parameters and the content/structure of data in `Message` and `Artifact` parts to prevent injection attacks or processing errors. +- **Resource Management:** Implement rate limiting, concurrency controls, and resource limits to protect agents from abuse or overload. +- **Data Privacy:** Adhere to all applicable privacy regulations for data exchanged in `Message` and `Artifact` parts. Minimize sensitive data transfer. + +For a comprehensive discussion, refer to the [Enterprise-Ready Features guide](./topics/enterprise-ready.md). + +## 11. A2A Compliance Requirements + +This section defines the normative requirements for A2A-compliant implementations. + +### 11.1. Agent Compliance + +For an agent to be considered **A2A-compliant**, it **MUST**: + +#### 11.1.1. Transport Support Requirements + +- **Support at least one transport**: Agents **MUST** implement at least one transport protocols as defined in [Section 3.2](#32-supported-transport-protocols). +- **Expose Agent Card**: **MUST** provide a valid `AgentCard` document as defined in [Section 5](#5-agent-discovery-the-agent-card). +- **Declare transport capabilities**: **MUST** accurately declare all supported transports in the `AgentCard` using `preferredTransport` and `additionalInterfaces` fields following the requirements in [Section 5.6](#56-transport-declaration-and-url-relationships). + +#### 11.1.2. Core Method Implementation + +**MUST** implement all of the following core methods via at least one supported transport: + +- `message/send` - Send messages and initiate tasks +- `tasks/get` - Retrieve task status and results +- `tasks/cancel` - Request task cancellation + +#### 11.1.3. Optional Method Implementation + +**MAY** implement the following optional methods: + +- `message/stream` - Streaming message interaction (requires `capabilities.streaming: true`) +- `tasks/resubscribe` - Resume streaming for existing tasks (requires `capabilities.streaming: true`) +- `tasks/pushNotificationConfig/set` - Configure push notifications (requires `capabilities.pushNotifications: true`) +- `tasks/pushNotificationConfig/get` - Retrieve push notification config (requires `capabilities.pushNotifications: true`) +- `tasks/pushNotificationConfig/list` - List push notification configs (requires `capabilities.pushNotifications: true`) +- `tasks/pushNotificationConfig/delete` - Delete push notification config (requires `capabilities.pushNotifications: true`) +- `agent/authenticatedExtendedCard` - Retrieve authenticated agent card (requires `supportsAuthenticatedExtendedCard: true`) + +#### 11.1.4. Multi-Transport Compliance + +If an agent supports additional transports (gRPC, HTTP+JSON), it **MUST**: + +- **Functional equivalence**: Provide identical functionality across all supported transports. +- **Consistent behavior**: Return semantically equivalent results for the same operations. +- **Transport-specific requirements**: Conform to all requirements defined in [Section 3.2](#32-supported-transport-protocols) for each supported transport. +- **Method mapping compliance**: Use the standard method mappings defined in [Section 3.5](#35-method-mapping-and-naming-conventions) for all supported transports. + +#### 11.1.5. Data Format Compliance + +- **JSON-RPC structure**: **MUST** use valid JSON-RPC 2.0 request/response objects as defined in [Section 6.11](#611-json-rpc-structures). +- **A2A data objects**: **MUST** use the data structures defined in [Section 6](#6-protocol-data-objects) for all protocol entities. +- **Error handling**: **MUST** use the error codes defined in [Section 8](#8-error-handling). + +### 11.2. Client Compliance + +For a client to be considered **A2A-compliant**, it **MUST**: + +#### 11.2.1. Transport Support + +- **Multi-transport capability**: **MUST** be able to communicate with agents using at least one transport protocols. +- **Agent Card processing**: **MUST** be able to parse and interpret `AgentCard` documents. +- **Transport selection**: **MUST** be able to select an appropriate transport from the agent's declared capabilities following the rules defined in [Section 5.6.3](#563-client-transport-selection-rules). + +#### 11.2.2. Protocol Implementation + +- **Core method usage**: **MUST** properly construct requests for at least `message/send` and `tasks/get` methods. +- **Error handling**: **MUST** properly handle all A2A error codes defined in [Section 8.2](#82-a2a-specific-errors). +- **Authentication**: **MUST** support at least one authentication method when interacting with agents that require authentication. + +#### 11.2.3. Optional Client Features + +Clients **MAY** implement: + +- **Multi-transport support**: Support for gRPC and/or HTTP+JSON transports. +- **Streaming support**: Handle streaming methods and Server-Sent Events. +- **Push notification handling**: Serve as webhook endpoints for push notifications. +- **Extended Agent Cards**: Retrieve and use authenticated extended agent cards. + +### 11.3. Compliance Testing + +Implementations **SHOULD** validate compliance through: + +- **Transport interoperability**: Test communication with agents using different transport implementations. +- **Method mapping verification**: Verify that all supported transports use the correct method names and URL patterns as defined in [Section 3.5](#35-method-mapping-and-naming-conventions). +- **Error handling**: Verify proper handling of all defined error conditions. +- **Data format validation**: Ensure JSON schemas match the TypeScript type definitions in [`types/src/types.ts`](https://github.com/a2aproject/A2A/blob/main/types/src/types.ts). +- **Multi-transport consistency**: For multi-transport agents, verify functional equivalence across all supported transports. \ No newline at end of file diff --git a/packages/a2a_dart/analysis_options.yaml b/packages/a2a_dart/analysis_options.yaml new file mode 100644 index 000000000..ead40d30c --- /dev/null +++ b/packages/a2a_dart/analysis_options.yaml @@ -0,0 +1,6 @@ +# Copyright 2025 The Flutter Authors. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +include: package:dart_flutter_team_lints/analysis_options.yaml + diff --git a/packages/a2a_dart/build.yaml b/packages/a2a_dart/build.yaml new file mode 100644 index 000000000..bd220c932 --- /dev/null +++ b/packages/a2a_dart/build.yaml @@ -0,0 +1,15 @@ +# Copyright 2025 The Flutter Authors. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +targets: + $default: + builders: + freezed: + enabled: true + json_serializable: + options: + explicit_to_json: true + source_gen:combining_builder: + options: + preamble: | diff --git a/packages/a2a_dart/example/README.md b/packages/a2a_dart/example/README.md new file mode 100644 index 000000000..cc743aa4c --- /dev/null +++ b/packages/a2a_dart/example/README.md @@ -0,0 +1,17 @@ +# A2A Dart Example + +This example demonstrates a simple client-server interaction using the `a2a_dart` package. + +## Running the Example + +1. **Start the server:** + + ```bash + dart run bin/server.dart + ``` + +2. **Run the client:** + + ```bash + dart run bin/client.dart + ``` diff --git a/packages/a2a_dart/example/bin/client.dart b/packages/a2a_dart/example/bin/client.dart new file mode 100644 index 000000000..194935804 --- /dev/null +++ b/packages/a2a_dart/example/bin/client.dart @@ -0,0 +1,104 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:logging/logging.dart'; +import 'package:uuid/uuid.dart'; + +/// This is an example of how to write a client for the A2A protocol. +/// It demonstrates the use of the A2AClient class to connect to an A2A server +/// and perform various operations. +/// +/// It connects to the server and asks it to start a countdown from 10 to zero. +/// Then at 5 it demonstrates how to pause the countdown, and then resumes it +/// after a three second pause. +void main() async { + Logger.root.level = Level.ALL; + Logger.root.onRecord.listen((record) { + print('${record.level.name}: ${record.time}: ${record.message}'); + }); + + final log = Logger('A2AClientExample'); + + await Future.delayed(const Duration(seconds: 1)); + + final client = A2AClient( + url: 'http://localhost:8080', + transport: HttpTransport(url: 'http://localhost:8080', log: log), + log: log, + ); + + try { + final agentCard = await client.getAgentCard(); + print('Agent: ${agentCard.name}'); + + final message = Message( + messageId: const Uuid().v4(), + role: Role.user, + parts: const [Part.text(text: 'start 10')], + ); + final stream = client.messageStream(message); + String? taskId; + + await for (final event in stream) { + taskId ??= event.taskId; + switch (event) { + case TaskStatusUpdate(): + final task = await client.getTask(event.taskId); + print('Task ${task.id} updated: ${task.status.state.name}'); + break; + case TaskArtifactUpdate(): + for (final part in event.artifact.parts) { + if (part is TextPart) { + print(part.text); + if (part.text.contains('Countdown at 5')) { + unawaited( + client.messageSend( + Message( + messageId: const Uuid().v4(), + role: Role.user, + parts: const [Part.text(text: 'pause')], + taskId: taskId, + ), + ), + ); + } + } + } + } + } + + print('---'); + + // Demonstrate messageSend + final task2 = await client.messageSend( + Message( + messageId: const Uuid().v4(), + role: Role.user, + parts: const [Part.text(text: 'pause')], + ), + ); + print('Created task ${task2.id}'); + + // Demonstrate listTasks + final tasks = await client.listTasks(); + print('Found ${tasks.tasks.length} tasks:'); + for (final t in tasks.tasks) { + print(' - ${t.id}'); + final task = await client.getTask(t.id); + // cancel the task + final canceledTask = await client.cancelTask(task.id); + print(' - Canceled task: ${canceledTask.id}'); + } + } on A2AException catch (exception) { + print('Error: $exception'); + exit(1); + } finally { + client.close(); + exit(0); + } +} diff --git a/packages/a2a_dart/example/pubspec.yaml b/packages/a2a_dart/example/pubspec.yaml new file mode 100644 index 000000000..0517f14d8 --- /dev/null +++ b/packages/a2a_dart/example/pubspec.yaml @@ -0,0 +1,16 @@ +# Copyright 2025 The Flutter Authors. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +name: a2a_dart_example +description: A simple example of using the a2a_dart package. +publish_to: "none" + +environment: + sdk: ">=3.9.2 <4.0.0" + +dependencies: + a2a_dart: + path: ../ + logging: ^1.2.0 + uuid: ^4.0.0 diff --git a/packages/a2a_dart/lib/a2a_dart.dart b/packages/a2a_dart/lib/a2a_dart.dart new file mode 100644 index 000000000..d08068325 --- /dev/null +++ b/packages/a2a_dart/lib/a2a_dart.dart @@ -0,0 +1,24 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// A library for building Agent-to-Agent (A2A) clients. +library; + +// Client exports. +export 'src/client/a2a_client.dart'; +export 'src/client/a2a_exception.dart'; +export 'src/client/http_transport.dart'; +export 'src/client/sse_transport.dart'; +export 'src/client/transport.dart'; +export 'src/core/agent_capabilities.dart'; +// Core data models and exceptions. +export 'src/core/agent_card.dart'; +export 'src/core/events.dart'; +export 'src/core/list_tasks_params.dart'; +export 'src/core/list_tasks_result.dart'; +export 'src/core/message.dart'; +export 'src/core/part.dart'; +export 'src/core/push_notification.dart'; +export 'src/core/security_scheme.dart'; +export 'src/core/task.dart'; diff --git a/packages/a2a_dart/lib/src/client/a2a_client.dart b/packages/a2a_dart/lib/src/client/a2a_client.dart new file mode 100644 index 000000000..610246529 --- /dev/null +++ b/packages/a2a_dart/lib/src/client/a2a_client.dart @@ -0,0 +1,409 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:logging/logging.dart'; + +import '../core/agent_card.dart'; +import '../core/events.dart'; +import '../core/list_tasks_params.dart'; +import '../core/list_tasks_result.dart'; +import '../core/message.dart'; +import '../core/push_notification.dart'; +import '../core/task.dart'; +import 'a2a_exception.dart'; +import 'http_transport.dart'; +import 'sse_transport.dart'; +import 'transport.dart'; + +/// A client for interacting with an A2A (Agent-to-Agent) server. +/// +/// This class provides methods for all the RPC calls defined in the A2A +/// specification. It handles the JSON-RPC 2.0 protocol and uses a [Transport] +/// instance to communicate with the server, which defaults to [HttpTransport]. +A2AException _exceptionFrom(Map error) { + final code = error['code'] as int; + final message = error['message'] as String; + final data = error['data'] as Map?; + + return switch (code) { + -32001 => A2AException.taskNotFound(message: message, data: data), + -32002 => A2AException.taskNotCancelable(message: message, data: data), + -32006 => A2AException.pushNotificationNotSupported( + message: message, + data: data, + ), + -32007 => A2AException.pushNotificationConfigNotFound( + message: message, + data: data, + ), + _ => A2AException.jsonRpc(code: code, message: message, data: data), + }; +} + +class A2AClient { + /// The base URL of the A2A server. + final String url; + + final Transport _transport; + final Logger? _log; + + /// Creates an [A2AClient] instance with a specific [Transport]. + /// + /// The [url] parameter is required and specifies the base URL of the A2A + /// server. + /// + /// The [transport] parameter specifies the communication layer. If omitted, + /// an [SseTransport] is created using the provided [url]. + /// + /// An optional [log] instance can be provided for logging client activities. + /// Creates an [A2AClient] instance. + /// + /// The [url] parameter is required and specifies the base URL of the A2A + /// server (e.g., `http://localhost:8000`). + /// + /// An optional [transport] can be provided to customize the communication + /// layer. If omitted, an [SseTransport] is created using the provided [url]. + /// + /// An optional [log] instance can be provided for logging client activities. + A2AClient({required this.url, Transport? transport, Logger? log}) + : _transport = transport ?? SseTransport(url: url, log: log), + _log = log; + + /// Creates an [A2AClient] by fetching an [AgentCard] and selecting the best + /// transport. + /// + /// Fetches the agent card from [agentCardUrl], determines the best transport + /// based on the card's capabilities (preferring streaming if available), + /// and returns a new [A2AClient] instance. + static Future fromAgentCardUrl( + String agentCardUrl, { + Logger? log, + }) async { + final tempTransport = HttpTransport(url: agentCardUrl, log: log); + final response = await tempTransport.get(''); + final agentCard = AgentCard.fromJson(response); + + final transport = (agentCard.capabilities.streaming ?? false) + ? SseTransport(url: agentCard.url, log: log) + : HttpTransport(url: agentCard.url, log: log); + + return A2AClient(url: agentCard.url, transport: transport, log: log); + } + + /// Fetches the public agent card from the server. + /// + /// The agent card contains metadata about the agent, such as its capabilities + /// and security schemes. This method typically requests the card from the + /// `/.well-known/agent-card.json` endpoint on the server. + /// + /// Returns an [AgentCard] object. + /// Throws an [A2AException] if the request fails or the response is invalid. + Future getAgentCard() async { + _log?.info('Fetching agent card...'); + final response = await _transport.get('/.well-known/agent-card.json'); + _log?.fine('Received agent card: $response'); + return AgentCard.fromJson(response); + } + + /// Fetches the authenticated extended agent card from the server. + /// + /// This method retrieves a potentially more detailed [AgentCard] that is only + /// available to authenticated users. It includes an `Authorization` header + /// with the provided Bearer [token] in the request to + /// `/.well-known/agent-card.json`. + /// + /// Returns an [AgentCard] object. + /// Throws an [A2AException] if the request fails or the response is invalid. + Future getAuthenticatedExtendedCard(String token) async { + _log?.info('Fetching authenticated agent card...'); + final response = await _transport.get( + '/.well-known/agent-card.json', + headers: {'Authorization': 'Bearer $token'}, + ); + _log?.fine('Received authenticated agent card: $response'); + return AgentCard.fromJson(response); + } + + /// Sends a message to the agent for a single-shot interaction via + /// `message/send`. + /// + /// This method is used for synchronous request/response interactions. The + /// server is expected to process the [message] and return a result relatively + /// quickly. The returned [Task] contains the initial state of the task as + /// reported by the server. + /// + /// For operations that are expected to take longer, consider using + /// [messageStream] or polling the task status using [getTask]. + /// + /// Returns the initial [Task] state. Throws an [A2AException] if the server + /// returns a JSON-RPC error. + Future messageSend(Message message) async { + _log?.info('Sending message: ${message.messageId}'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'message/send', + 'params': {'message': message.toJson()}, + 'id': 0, + }); + _log?.fine('Received response from message/send: $response'); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + return Task.fromJson(response['result'] as Map); + } + + /// Sends a message to the agent and subscribes to real-time updates via + /// `message/stream`. + /// + /// This method is used for streaming interactions. The agent can send + /// multiple updates over time. The returned stream emits [Event] objects as + /// they are received from the server, typically using Server-Sent Events + /// (SSE). + /// + /// Returns a [Stream] of [Event] objects. The stream will emit an + /// [A2AException] if the server sends a JSON-RPC error within the event + /// stream. + Stream messageStream(Message message) { + _log?.info('Sending message for stream: ${message.messageId}'); + final stream = _transport.sendStream({ + 'jsonrpc': '2.0', + 'method': 'message/stream', + 'params': {'message': message.toJson()}, + }); + + return stream.transform( + StreamTransformer.fromHandlers( + handleData: (data, sink) { + _log?.fine('Received event from stream: $data'); + if (data.containsKey('error')) { + sink.addError( + _exceptionFrom(data['error'] as Map), + ); + } else { + if (data['kind'] != null) { + // Skip keepalive events + sink.add(Event.fromJson(data)); + } + } + }, + ), + ); + } + + /// Retrieves the current state of a task from the server using `tasks/get`. + /// + /// This method is used to poll the status of a task, identified by [taskId], + /// that was previously initiated (e.g., via [messageSend]). + /// + /// Returns the current [Task] state. Throws an [A2AException] if the server + /// returns a JSON-RPC error (e.g., task not found). + Future getTask(String taskId) async { + _log?.info('Getting task: $taskId'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'tasks/get', + 'params': {'id': taskId}, + 'id': 0, + }); + _log?.fine('Received response from tasks/get: $response'); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + return Task.fromJson(response['result'] as Map); + } + + /// Retrieves a list of tasks from the server using `tasks/list`. + /// + /// The optional [params] of type [ListTasksParams] can be provided to filter, + /// sort, and paginate the task list. + /// + /// Returns a [ListTasksResult] containing the list of tasks and pagination + /// info. Throws an [A2AException] if the server returns a JSON-RPC error. + Future listTasks([ListTasksParams? params]) async { + _log?.info('Listing tasks...'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'tasks/list', + 'params': params?.toJson() ?? {}, + 'id': 0, + }); + _log?.fine('Received response from tasks/list: $response'); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + return ListTasksResult.fromJson(response['result'] as Map); + } + + /// Requests the cancellation of an ongoing task using `tasks/cancel`. + /// + /// The server will attempt to cancel the task identified by [taskId]. + /// Success is not guaranteed, as the task might have already completed or may + /// not support cancellation. + /// + /// Returns the updated [Task] state after the cancellation request. + /// Throws an [A2AException] if the server returns a JSON-RPC error. + Future cancelTask(String taskId) async { + _log?.info('Canceling task: $taskId'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'tasks/cancel', + 'params': {'id': taskId}, + 'id': 0, + }); + _log?.fine('Received response from tasks/cancel: $response'); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + return Task.fromJson(response['result'] as Map); + } + + /// Resubscribes to an SSE stream for an ongoing task using + /// `tasks/resubscribe`. + /// + /// This method allows a client to reconnect to the event stream of a task + /// identified by [taskId], for instance, after a network interruption. The + /// returned stream will emit subsequent [Event] objects for the task. + /// + /// Returns a [Stream] of [Event] objects. The stream will emit an + /// [A2AException] if the server returns a JSON-RPC error. + Stream resubscribeToTask(String taskId) { + _log?.info('Resubscribing to task: $taskId'); + return _transport + .sendStream({ + 'jsonrpc': '2.0', + 'method': 'tasks/resubscribe', + 'params': {'id': taskId}, + }) + .map((data) { + _log?.fine('Received event from stream: $data'); + if (data.containsKey('error')) { + throw _exceptionFrom(data['error'] as Map); + } + return Event.fromJson(data); + }); + } + + /// Closes the underlying transport connection. + /// + /// This should be called when the client is no longer needed to release + /// resources. + void close() { + _transport.close(); + } + + /// Sets or updates the push notification configuration for a task. + /// + /// Uses the `tasks/pushNotificationConfig/set` method. + /// + /// Returns the updated [TaskPushNotificationConfig]. + /// Throws an [A2AException] if the server returns a JSON-RPC error. + Future setPushNotificationConfig( + TaskPushNotificationConfig params, + ) async { + _log?.info('Setting push notification config for task: ${params.taskId}'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'tasks/pushNotificationConfig/set', + 'params': params.toJson(), + 'id': 0, + }); + _log?.fine( + 'Received response from tasks/pushNotificationConfig/set: $response', + ); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + return TaskPushNotificationConfig.fromJson( + response['result'] as Map, + ); + } + + /// Retrieves a specific push notification configuration for a task. + /// + /// Uses the `tasks/pushNotificationConfig/get` method, identified by [taskId] + /// and [configId]. + /// + /// Returns the requested [TaskPushNotificationConfig]. + /// Throws an [A2AException] if the server returns a JSON-RPC error. + Future getPushNotificationConfig( + String taskId, + String configId, + ) async { + _log?.info('Getting push notification config $configId for task: $taskId'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'tasks/pushNotificationConfig/get', + 'params': {'id': taskId, 'pushNotificationConfigId': configId}, + 'id': 0, + }); + _log?.fine( + 'Received response from tasks/pushNotificationConfig/get: $response', + ); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + return TaskPushNotificationConfig.fromJson( + response['result'] as Map, + ); + } + + /// Lists all push notification configurations for a given task. + /// + /// Uses the `tasks/pushNotificationConfig/list` method, identified by [taskId]. + /// + /// Returns a List of [PushNotificationConfig] objects. + /// Throws an [A2AException] if the server returns a JSON-RPC error. + Future> listPushNotificationConfigs( + String taskId, + ) async { + _log?.info('Listing push notification configs for task: $taskId'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'tasks/pushNotificationConfig/list', + 'params': {'id': taskId}, + 'id': 0, + }); + _log?.fine( + 'Received response from tasks/pushNotificationConfig/list: $response', + ); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + final result = response['result'] as Map; + final configs = result['configs'] as List; + return configs + .map( + (item) => + PushNotificationConfig.fromJson(item as Map), + ) + .toList(); + } + + /// Deletes a specific push notification configuration for a task. + /// + /// Uses the `tasks/pushNotificationConfig/delete` method, identified by [taskId] + /// and [configId]. + /// + /// Throws an [A2AException] if the server returns a JSON-RPC error. + Future deletePushNotificationConfig( + String taskId, + String configId, + ) async { + _log?.info('Deleting push notification config $configId for task: $taskId'); + final response = await _transport.send({ + 'jsonrpc': '2.0', + 'method': 'tasks/pushNotificationConfig/delete', + 'params': {'id': taskId, 'pushNotificationConfigId': configId}, + 'id': 0, + }); + _log?.fine( + 'Received response from tasks/pushNotificationConfig/delete: $response', + ); + if (response.containsKey('error')) { + throw _exceptionFrom(response['error'] as Map); + } + } +} diff --git a/packages/a2a_dart/lib/src/client/a2a_exception.dart b/packages/a2a_dart/lib/src/client/a2a_exception.dart new file mode 100644 index 000000000..c437470cc --- /dev/null +++ b/packages/a2a_dart/lib/src/client/a2a_exception.dart @@ -0,0 +1,87 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'a2a_exception.freezed.dart'; +part 'a2a_exception.g.dart'; + +/// Base class for exceptions thrown by the A2A client. +/// +/// This sealed class hierarchy represents different categories of errors +/// that can occur during communication with an A2A server. +@freezed +sealed class A2AException with _$A2AException implements Exception { + /// Represents a JSON-RPC error returned by the server. + /// + /// This exception is thrown when the server responds with a JSON-RPC error + /// object, indicating a problem with the request as understood by the A2A + /// protocol. + const factory A2AException.jsonRpc({ + /// The integer error code as defined by the JSON-RPC 2.0 specification + /// or A2A-specific error codes. + required int code, + + /// A human-readable string describing the error. + required String message, + + /// Optional additional data provided by the server about the error. + Map? data, + }) = A2AJsonRpcException; + + const factory A2AException.taskNotFound({ + required String message, + Map? data, + }) = A2ATaskNotFoundException; + + const factory A2AException.taskNotCancelable({ + required String message, + Map? data, + }) = A2ATaskNotCancelableException; + + const factory A2AException.pushNotificationNotSupported({ + required String message, + Map? data, + }) = A2APushNotificationNotSupportedException; + + const factory A2AException.pushNotificationConfigNotFound({ + required String message, + Map? data, + }) = A2APushNotificationConfigNotFoundException; + + /// Represents an error related to the HTTP transport layer. + /// + /// This exception is thrown when an HTTP request fails with a non-2xx status + /// code, and the issue is not a specific JSON-RPC error. + const factory A2AException.http({ + /// The HTTP status code (e.g., 404, 500). + required int statusCode, + + /// An optional human-readable reason phrase associated with the status + /// code. + String? reason, + }) = A2AHttpException; + + /// Represents a network connectivity issue. + /// + /// This exception is thrown when a connection to the server cannot be + /// established or is interrupted. + const factory A2AException.network({ + /// A message describing the network error. + required String message, + }) = A2ANetworkException; + + /// Represents an error during the parsing of a server response. + /// + /// This exception is thrown if the client fails to parse the server's + /// response, for example, due to malformed JSON. + const factory A2AException.parsing({ + /// A message describing the parsing failure. + required String message, + }) = A2AParsingException; + + /// Deserializes an [A2AException] from a JSON object. + factory A2AException.fromJson(Map json) => + _$A2AExceptionFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/client/a2a_exception.freezed.dart b/packages/a2a_dart/lib/src/client/a2a_exception.freezed.dart new file mode 100644 index 000000000..fda4af3d1 --- /dev/null +++ b/packages/a2a_dart/lib/src/client/a2a_exception.freezed.dart @@ -0,0 +1,908 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'a2a_exception.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +A2AException _$A2AExceptionFromJson( + Map json +) { + switch (json['runtimeType']) { + case 'jsonRpc': + return A2AJsonRpcException.fromJson( + json + ); + case 'taskNotFound': + return A2ATaskNotFoundException.fromJson( + json + ); + case 'taskNotCancelable': + return A2ATaskNotCancelableException.fromJson( + json + ); + case 'pushNotificationNotSupported': + return A2APushNotificationNotSupportedException.fromJson( + json + ); + case 'pushNotificationConfigNotFound': + return A2APushNotificationConfigNotFoundException.fromJson( + json + ); + case 'http': + return A2AHttpException.fromJson( + json + ); + case 'network': + return A2ANetworkException.fromJson( + json + ); + case 'parsing': + return A2AParsingException.fromJson( + json + ); + + default: + throw CheckedFromJsonException( + json, + 'runtimeType', + 'A2AException', + 'Invalid union type "${json['runtimeType']}"!' +); + } + +} + +/// @nodoc +mixin _$A2AException { + + + + /// Serializes this A2AException to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2AException); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => runtimeType.hashCode; + +@override +String toString() { + return 'A2AException()'; +} + + +} + +/// @nodoc +class $A2AExceptionCopyWith<$Res> { +$A2AExceptionCopyWith(A2AException _, $Res Function(A2AException) __); +} + + +/// Adds pattern-matching-related methods to [A2AException]. +extension A2AExceptionPatterns on A2AException { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( A2AJsonRpcException value)? jsonRpc,TResult Function( A2ATaskNotFoundException value)? taskNotFound,TResult Function( A2ATaskNotCancelableException value)? taskNotCancelable,TResult Function( A2APushNotificationNotSupportedException value)? pushNotificationNotSupported,TResult Function( A2APushNotificationConfigNotFoundException value)? pushNotificationConfigNotFound,TResult Function( A2AHttpException value)? http,TResult Function( A2ANetworkException value)? network,TResult Function( A2AParsingException value)? parsing,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case A2AJsonRpcException() when jsonRpc != null: +return jsonRpc(_that);case A2ATaskNotFoundException() when taskNotFound != null: +return taskNotFound(_that);case A2ATaskNotCancelableException() when taskNotCancelable != null: +return taskNotCancelable(_that);case A2APushNotificationNotSupportedException() when pushNotificationNotSupported != null: +return pushNotificationNotSupported(_that);case A2APushNotificationConfigNotFoundException() when pushNotificationConfigNotFound != null: +return pushNotificationConfigNotFound(_that);case A2AHttpException() when http != null: +return http(_that);case A2ANetworkException() when network != null: +return network(_that);case A2AParsingException() when parsing != null: +return parsing(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( A2AJsonRpcException value) jsonRpc,required TResult Function( A2ATaskNotFoundException value) taskNotFound,required TResult Function( A2ATaskNotCancelableException value) taskNotCancelable,required TResult Function( A2APushNotificationNotSupportedException value) pushNotificationNotSupported,required TResult Function( A2APushNotificationConfigNotFoundException value) pushNotificationConfigNotFound,required TResult Function( A2AHttpException value) http,required TResult Function( A2ANetworkException value) network,required TResult Function( A2AParsingException value) parsing,}){ +final _that = this; +switch (_that) { +case A2AJsonRpcException(): +return jsonRpc(_that);case A2ATaskNotFoundException(): +return taskNotFound(_that);case A2ATaskNotCancelableException(): +return taskNotCancelable(_that);case A2APushNotificationNotSupportedException(): +return pushNotificationNotSupported(_that);case A2APushNotificationConfigNotFoundException(): +return pushNotificationConfigNotFound(_that);case A2AHttpException(): +return http(_that);case A2ANetworkException(): +return network(_that);case A2AParsingException(): +return parsing(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( A2AJsonRpcException value)? jsonRpc,TResult? Function( A2ATaskNotFoundException value)? taskNotFound,TResult? Function( A2ATaskNotCancelableException value)? taskNotCancelable,TResult? Function( A2APushNotificationNotSupportedException value)? pushNotificationNotSupported,TResult? Function( A2APushNotificationConfigNotFoundException value)? pushNotificationConfigNotFound,TResult? Function( A2AHttpException value)? http,TResult? Function( A2ANetworkException value)? network,TResult? Function( A2AParsingException value)? parsing,}){ +final _that = this; +switch (_that) { +case A2AJsonRpcException() when jsonRpc != null: +return jsonRpc(_that);case A2ATaskNotFoundException() when taskNotFound != null: +return taskNotFound(_that);case A2ATaskNotCancelableException() when taskNotCancelable != null: +return taskNotCancelable(_that);case A2APushNotificationNotSupportedException() when pushNotificationNotSupported != null: +return pushNotificationNotSupported(_that);case A2APushNotificationConfigNotFoundException() when pushNotificationConfigNotFound != null: +return pushNotificationConfigNotFound(_that);case A2AHttpException() when http != null: +return http(_that);case A2ANetworkException() when network != null: +return network(_that);case A2AParsingException() when parsing != null: +return parsing(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( int code, String message, Map? data)? jsonRpc,TResult Function( String message, Map? data)? taskNotFound,TResult Function( String message, Map? data)? taskNotCancelable,TResult Function( String message, Map? data)? pushNotificationNotSupported,TResult Function( String message, Map? data)? pushNotificationConfigNotFound,TResult Function( int statusCode, String? reason)? http,TResult Function( String message)? network,TResult Function( String message)? parsing,required TResult orElse(),}) {final _that = this; +switch (_that) { +case A2AJsonRpcException() when jsonRpc != null: +return jsonRpc(_that.code,_that.message,_that.data);case A2ATaskNotFoundException() when taskNotFound != null: +return taskNotFound(_that.message,_that.data);case A2ATaskNotCancelableException() when taskNotCancelable != null: +return taskNotCancelable(_that.message,_that.data);case A2APushNotificationNotSupportedException() when pushNotificationNotSupported != null: +return pushNotificationNotSupported(_that.message,_that.data);case A2APushNotificationConfigNotFoundException() when pushNotificationConfigNotFound != null: +return pushNotificationConfigNotFound(_that.message,_that.data);case A2AHttpException() when http != null: +return http(_that.statusCode,_that.reason);case A2ANetworkException() when network != null: +return network(_that.message);case A2AParsingException() when parsing != null: +return parsing(_that.message);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( int code, String message, Map? data) jsonRpc,required TResult Function( String message, Map? data) taskNotFound,required TResult Function( String message, Map? data) taskNotCancelable,required TResult Function( String message, Map? data) pushNotificationNotSupported,required TResult Function( String message, Map? data) pushNotificationConfigNotFound,required TResult Function( int statusCode, String? reason) http,required TResult Function( String message) network,required TResult Function( String message) parsing,}) {final _that = this; +switch (_that) { +case A2AJsonRpcException(): +return jsonRpc(_that.code,_that.message,_that.data);case A2ATaskNotFoundException(): +return taskNotFound(_that.message,_that.data);case A2ATaskNotCancelableException(): +return taskNotCancelable(_that.message,_that.data);case A2APushNotificationNotSupportedException(): +return pushNotificationNotSupported(_that.message,_that.data);case A2APushNotificationConfigNotFoundException(): +return pushNotificationConfigNotFound(_that.message,_that.data);case A2AHttpException(): +return http(_that.statusCode,_that.reason);case A2ANetworkException(): +return network(_that.message);case A2AParsingException(): +return parsing(_that.message);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( int code, String message, Map? data)? jsonRpc,TResult? Function( String message, Map? data)? taskNotFound,TResult? Function( String message, Map? data)? taskNotCancelable,TResult? Function( String message, Map? data)? pushNotificationNotSupported,TResult? Function( String message, Map? data)? pushNotificationConfigNotFound,TResult? Function( int statusCode, String? reason)? http,TResult? Function( String message)? network,TResult? Function( String message)? parsing,}) {final _that = this; +switch (_that) { +case A2AJsonRpcException() when jsonRpc != null: +return jsonRpc(_that.code,_that.message,_that.data);case A2ATaskNotFoundException() when taskNotFound != null: +return taskNotFound(_that.message,_that.data);case A2ATaskNotCancelableException() when taskNotCancelable != null: +return taskNotCancelable(_that.message,_that.data);case A2APushNotificationNotSupportedException() when pushNotificationNotSupported != null: +return pushNotificationNotSupported(_that.message,_that.data);case A2APushNotificationConfigNotFoundException() when pushNotificationConfigNotFound != null: +return pushNotificationConfigNotFound(_that.message,_that.data);case A2AHttpException() when http != null: +return http(_that.statusCode,_that.reason);case A2ANetworkException() when network != null: +return network(_that.message);case A2AParsingException() when parsing != null: +return parsing(_that.message);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class A2AJsonRpcException implements A2AException { + const A2AJsonRpcException({required this.code, required this.message, final Map? data, final String? $type}): _data = data,$type = $type ?? 'jsonRpc'; + factory A2AJsonRpcException.fromJson(Map json) => _$A2AJsonRpcExceptionFromJson(json); + +/// The integer error code as defined by the JSON-RPC 2.0 specification +/// or A2A-specific error codes. + final int code; +/// A human-readable string describing the error. + final String message; +/// Optional additional data provided by the server about the error. + final Map? _data; +/// Optional additional data provided by the server about the error. + Map? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableMapView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2AJsonRpcExceptionCopyWith get copyWith => _$A2AJsonRpcExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2AJsonRpcExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2AJsonRpcException&&(identical(other.code, code) || other.code == code)&&(identical(other.message, message) || other.message == message)&&const DeepCollectionEquality().equals(other._data, _data)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,code,message,const DeepCollectionEquality().hash(_data)); + +@override +String toString() { + return 'A2AException.jsonRpc(code: $code, message: $message, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class $A2AJsonRpcExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2AJsonRpcExceptionCopyWith(A2AJsonRpcException value, $Res Function(A2AJsonRpcException) _then) = _$A2AJsonRpcExceptionCopyWithImpl; +@useResult +$Res call({ + int code, String message, Map? data +}); + + + + +} +/// @nodoc +class _$A2AJsonRpcExceptionCopyWithImpl<$Res> + implements $A2AJsonRpcExceptionCopyWith<$Res> { + _$A2AJsonRpcExceptionCopyWithImpl(this._self, this._then); + + final A2AJsonRpcException _self; + final $Res Function(A2AJsonRpcException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? code = null,Object? message = null,Object? data = freezed,}) { + return _then(A2AJsonRpcException( +code: null == code ? _self.code : code // ignore: cast_nullable_to_non_nullable +as int,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class A2ATaskNotFoundException implements A2AException { + const A2ATaskNotFoundException({required this.message, final Map? data, final String? $type}): _data = data,$type = $type ?? 'taskNotFound'; + factory A2ATaskNotFoundException.fromJson(Map json) => _$A2ATaskNotFoundExceptionFromJson(json); + + final String message; + final Map? _data; + Map? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableMapView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2ATaskNotFoundExceptionCopyWith get copyWith => _$A2ATaskNotFoundExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2ATaskNotFoundExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2ATaskNotFoundException&&(identical(other.message, message) || other.message == message)&&const DeepCollectionEquality().equals(other._data, _data)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,message,const DeepCollectionEquality().hash(_data)); + +@override +String toString() { + return 'A2AException.taskNotFound(message: $message, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class $A2ATaskNotFoundExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2ATaskNotFoundExceptionCopyWith(A2ATaskNotFoundException value, $Res Function(A2ATaskNotFoundException) _then) = _$A2ATaskNotFoundExceptionCopyWithImpl; +@useResult +$Res call({ + String message, Map? data +}); + + + + +} +/// @nodoc +class _$A2ATaskNotFoundExceptionCopyWithImpl<$Res> + implements $A2ATaskNotFoundExceptionCopyWith<$Res> { + _$A2ATaskNotFoundExceptionCopyWithImpl(this._self, this._then); + + final A2ATaskNotFoundException _self; + final $Res Function(A2ATaskNotFoundException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? message = null,Object? data = freezed,}) { + return _then(A2ATaskNotFoundException( +message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class A2ATaskNotCancelableException implements A2AException { + const A2ATaskNotCancelableException({required this.message, final Map? data, final String? $type}): _data = data,$type = $type ?? 'taskNotCancelable'; + factory A2ATaskNotCancelableException.fromJson(Map json) => _$A2ATaskNotCancelableExceptionFromJson(json); + + final String message; + final Map? _data; + Map? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableMapView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2ATaskNotCancelableExceptionCopyWith get copyWith => _$A2ATaskNotCancelableExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2ATaskNotCancelableExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2ATaskNotCancelableException&&(identical(other.message, message) || other.message == message)&&const DeepCollectionEquality().equals(other._data, _data)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,message,const DeepCollectionEquality().hash(_data)); + +@override +String toString() { + return 'A2AException.taskNotCancelable(message: $message, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class $A2ATaskNotCancelableExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2ATaskNotCancelableExceptionCopyWith(A2ATaskNotCancelableException value, $Res Function(A2ATaskNotCancelableException) _then) = _$A2ATaskNotCancelableExceptionCopyWithImpl; +@useResult +$Res call({ + String message, Map? data +}); + + + + +} +/// @nodoc +class _$A2ATaskNotCancelableExceptionCopyWithImpl<$Res> + implements $A2ATaskNotCancelableExceptionCopyWith<$Res> { + _$A2ATaskNotCancelableExceptionCopyWithImpl(this._self, this._then); + + final A2ATaskNotCancelableException _self; + final $Res Function(A2ATaskNotCancelableException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? message = null,Object? data = freezed,}) { + return _then(A2ATaskNotCancelableException( +message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class A2APushNotificationNotSupportedException implements A2AException { + const A2APushNotificationNotSupportedException({required this.message, final Map? data, final String? $type}): _data = data,$type = $type ?? 'pushNotificationNotSupported'; + factory A2APushNotificationNotSupportedException.fromJson(Map json) => _$A2APushNotificationNotSupportedExceptionFromJson(json); + + final String message; + final Map? _data; + Map? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableMapView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2APushNotificationNotSupportedExceptionCopyWith get copyWith => _$A2APushNotificationNotSupportedExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2APushNotificationNotSupportedExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2APushNotificationNotSupportedException&&(identical(other.message, message) || other.message == message)&&const DeepCollectionEquality().equals(other._data, _data)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,message,const DeepCollectionEquality().hash(_data)); + +@override +String toString() { + return 'A2AException.pushNotificationNotSupported(message: $message, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class $A2APushNotificationNotSupportedExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2APushNotificationNotSupportedExceptionCopyWith(A2APushNotificationNotSupportedException value, $Res Function(A2APushNotificationNotSupportedException) _then) = _$A2APushNotificationNotSupportedExceptionCopyWithImpl; +@useResult +$Res call({ + String message, Map? data +}); + + + + +} +/// @nodoc +class _$A2APushNotificationNotSupportedExceptionCopyWithImpl<$Res> + implements $A2APushNotificationNotSupportedExceptionCopyWith<$Res> { + _$A2APushNotificationNotSupportedExceptionCopyWithImpl(this._self, this._then); + + final A2APushNotificationNotSupportedException _self; + final $Res Function(A2APushNotificationNotSupportedException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? message = null,Object? data = freezed,}) { + return _then(A2APushNotificationNotSupportedException( +message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class A2APushNotificationConfigNotFoundException implements A2AException { + const A2APushNotificationConfigNotFoundException({required this.message, final Map? data, final String? $type}): _data = data,$type = $type ?? 'pushNotificationConfigNotFound'; + factory A2APushNotificationConfigNotFoundException.fromJson(Map json) => _$A2APushNotificationConfigNotFoundExceptionFromJson(json); + + final String message; + final Map? _data; + Map? get data { + final value = _data; + if (value == null) return null; + if (_data is EqualUnmodifiableMapView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2APushNotificationConfigNotFoundExceptionCopyWith get copyWith => _$A2APushNotificationConfigNotFoundExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2APushNotificationConfigNotFoundExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2APushNotificationConfigNotFoundException&&(identical(other.message, message) || other.message == message)&&const DeepCollectionEquality().equals(other._data, _data)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,message,const DeepCollectionEquality().hash(_data)); + +@override +String toString() { + return 'A2AException.pushNotificationConfigNotFound(message: $message, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class $A2APushNotificationConfigNotFoundExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2APushNotificationConfigNotFoundExceptionCopyWith(A2APushNotificationConfigNotFoundException value, $Res Function(A2APushNotificationConfigNotFoundException) _then) = _$A2APushNotificationConfigNotFoundExceptionCopyWithImpl; +@useResult +$Res call({ + String message, Map? data +}); + + + + +} +/// @nodoc +class _$A2APushNotificationConfigNotFoundExceptionCopyWithImpl<$Res> + implements $A2APushNotificationConfigNotFoundExceptionCopyWith<$Res> { + _$A2APushNotificationConfigNotFoundExceptionCopyWithImpl(this._self, this._then); + + final A2APushNotificationConfigNotFoundException _self; + final $Res Function(A2APushNotificationConfigNotFoundException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? message = null,Object? data = freezed,}) { + return _then(A2APushNotificationConfigNotFoundException( +message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String,data: freezed == data ? _self._data : data // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class A2AHttpException implements A2AException { + const A2AHttpException({required this.statusCode, this.reason, final String? $type}): $type = $type ?? 'http'; + factory A2AHttpException.fromJson(Map json) => _$A2AHttpExceptionFromJson(json); + +/// The HTTP status code (e.g., 404, 500). + final int statusCode; +/// An optional human-readable reason phrase associated with the status +/// code. + final String? reason; + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2AHttpExceptionCopyWith get copyWith => _$A2AHttpExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2AHttpExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2AHttpException&&(identical(other.statusCode, statusCode) || other.statusCode == statusCode)&&(identical(other.reason, reason) || other.reason == reason)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,statusCode,reason); + +@override +String toString() { + return 'A2AException.http(statusCode: $statusCode, reason: $reason)'; +} + + +} + +/// @nodoc +abstract mixin class $A2AHttpExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2AHttpExceptionCopyWith(A2AHttpException value, $Res Function(A2AHttpException) _then) = _$A2AHttpExceptionCopyWithImpl; +@useResult +$Res call({ + int statusCode, String? reason +}); + + + + +} +/// @nodoc +class _$A2AHttpExceptionCopyWithImpl<$Res> + implements $A2AHttpExceptionCopyWith<$Res> { + _$A2AHttpExceptionCopyWithImpl(this._self, this._then); + + final A2AHttpException _self; + final $Res Function(A2AHttpException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? statusCode = null,Object? reason = freezed,}) { + return _then(A2AHttpException( +statusCode: null == statusCode ? _self.statusCode : statusCode // ignore: cast_nullable_to_non_nullable +as int,reason: freezed == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class A2ANetworkException implements A2AException { + const A2ANetworkException({required this.message, final String? $type}): $type = $type ?? 'network'; + factory A2ANetworkException.fromJson(Map json) => _$A2ANetworkExceptionFromJson(json); + +/// A message describing the network error. + final String message; + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2ANetworkExceptionCopyWith get copyWith => _$A2ANetworkExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2ANetworkExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2ANetworkException&&(identical(other.message, message) || other.message == message)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,message); + +@override +String toString() { + return 'A2AException.network(message: $message)'; +} + + +} + +/// @nodoc +abstract mixin class $A2ANetworkExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2ANetworkExceptionCopyWith(A2ANetworkException value, $Res Function(A2ANetworkException) _then) = _$A2ANetworkExceptionCopyWithImpl; +@useResult +$Res call({ + String message +}); + + + + +} +/// @nodoc +class _$A2ANetworkExceptionCopyWithImpl<$Res> + implements $A2ANetworkExceptionCopyWith<$Res> { + _$A2ANetworkExceptionCopyWithImpl(this._self, this._then); + + final A2ANetworkException _self; + final $Res Function(A2ANetworkException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? message = null,}) { + return _then(A2ANetworkException( +message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class A2AParsingException implements A2AException { + const A2AParsingException({required this.message, final String? $type}): $type = $type ?? 'parsing'; + factory A2AParsingException.fromJson(Map json) => _$A2AParsingExceptionFromJson(json); + +/// A message describing the parsing failure. + final String message; + +@JsonKey(name: 'runtimeType') +final String $type; + + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$A2AParsingExceptionCopyWith get copyWith => _$A2AParsingExceptionCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$A2AParsingExceptionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is A2AParsingException&&(identical(other.message, message) || other.message == message)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,message); + +@override +String toString() { + return 'A2AException.parsing(message: $message)'; +} + + +} + +/// @nodoc +abstract mixin class $A2AParsingExceptionCopyWith<$Res> implements $A2AExceptionCopyWith<$Res> { + factory $A2AParsingExceptionCopyWith(A2AParsingException value, $Res Function(A2AParsingException) _then) = _$A2AParsingExceptionCopyWithImpl; +@useResult +$Res call({ + String message +}); + + + + +} +/// @nodoc +class _$A2AParsingExceptionCopyWithImpl<$Res> + implements $A2AParsingExceptionCopyWith<$Res> { + _$A2AParsingExceptionCopyWithImpl(this._self, this._then); + + final A2AParsingException _self; + final $Res Function(A2AParsingException) _then; + +/// Create a copy of A2AException +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') $Res call({Object? message = null,}) { + return _then(A2AParsingException( +message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/client/a2a_exception.g.dart b/packages/a2a_dart/lib/src/client/a2a_exception.g.dart new file mode 100644 index 000000000..26695abfa --- /dev/null +++ b/packages/a2a_dart/lib/src/client/a2a_exception.g.dart @@ -0,0 +1,129 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'a2a_exception.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +A2AJsonRpcException _$A2AJsonRpcExceptionFromJson(Map json) => + A2AJsonRpcException( + code: (json['code'] as num).toInt(), + message: json['message'] as String, + data: json['data'] as Map?, + $type: json['runtimeType'] as String?, + ); + +Map _$A2AJsonRpcExceptionToJson( + A2AJsonRpcException instance, +) => { + 'code': instance.code, + 'message': instance.message, + 'data': instance.data, + 'runtimeType': instance.$type, +}; + +A2ATaskNotFoundException _$A2ATaskNotFoundExceptionFromJson( + Map json, +) => A2ATaskNotFoundException( + message: json['message'] as String, + data: json['data'] as Map?, + $type: json['runtimeType'] as String?, +); + +Map _$A2ATaskNotFoundExceptionToJson( + A2ATaskNotFoundException instance, +) => { + 'message': instance.message, + 'data': instance.data, + 'runtimeType': instance.$type, +}; + +A2ATaskNotCancelableException _$A2ATaskNotCancelableExceptionFromJson( + Map json, +) => A2ATaskNotCancelableException( + message: json['message'] as String, + data: json['data'] as Map?, + $type: json['runtimeType'] as String?, +); + +Map _$A2ATaskNotCancelableExceptionToJson( + A2ATaskNotCancelableException instance, +) => { + 'message': instance.message, + 'data': instance.data, + 'runtimeType': instance.$type, +}; + +A2APushNotificationNotSupportedException +_$A2APushNotificationNotSupportedExceptionFromJson(Map json) => + A2APushNotificationNotSupportedException( + message: json['message'] as String, + data: json['data'] as Map?, + $type: json['runtimeType'] as String?, + ); + +Map _$A2APushNotificationNotSupportedExceptionToJson( + A2APushNotificationNotSupportedException instance, +) => { + 'message': instance.message, + 'data': instance.data, + 'runtimeType': instance.$type, +}; + +A2APushNotificationConfigNotFoundException +_$A2APushNotificationConfigNotFoundExceptionFromJson( + Map json, +) => A2APushNotificationConfigNotFoundException( + message: json['message'] as String, + data: json['data'] as Map?, + $type: json['runtimeType'] as String?, +); + +Map _$A2APushNotificationConfigNotFoundExceptionToJson( + A2APushNotificationConfigNotFoundException instance, +) => { + 'message': instance.message, + 'data': instance.data, + 'runtimeType': instance.$type, +}; + +A2AHttpException _$A2AHttpExceptionFromJson(Map json) => + A2AHttpException( + statusCode: (json['statusCode'] as num).toInt(), + reason: json['reason'] as String?, + $type: json['runtimeType'] as String?, + ); + +Map _$A2AHttpExceptionToJson(A2AHttpException instance) => + { + 'statusCode': instance.statusCode, + 'reason': instance.reason, + 'runtimeType': instance.$type, + }; + +A2ANetworkException _$A2ANetworkExceptionFromJson(Map json) => + A2ANetworkException( + message: json['message'] as String, + $type: json['runtimeType'] as String?, + ); + +Map _$A2ANetworkExceptionToJson( + A2ANetworkException instance, +) => { + 'message': instance.message, + 'runtimeType': instance.$type, +}; + +A2AParsingException _$A2AParsingExceptionFromJson(Map json) => + A2AParsingException( + message: json['message'] as String, + $type: json['runtimeType'] as String?, + ); + +Map _$A2AParsingExceptionToJson( + A2AParsingException instance, +) => { + 'message': instance.message, + 'runtimeType': instance.$type, +}; diff --git a/packages/a2a_dart/lib/src/client/a2a_handler.dart b/packages/a2a_dart/lib/src/client/a2a_handler.dart new file mode 100644 index 000000000..dcb96145f --- /dev/null +++ b/packages/a2a_dart/lib/src/client/a2a_handler.dart @@ -0,0 +1,46 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +/// A handler for intercepting and processing A2A requests and responses. +abstract class A2AHandler { + /// Handles the request and can modify it before it is sent. + Future> handleRequest(Map request); + + /// Handles the response and can modify it before it is returned to the + /// caller. + Future> handleResponse(Map response); +} + +/// A pipeline for executing a series of [A2AHandler]s. +class A2AHandlerPipeline { + /// Creates an [A2AHandlerPipeline]. + A2AHandlerPipeline({required this.handlers}); + + /// The list of handlers to execute. + final List handlers; + + /// Executes the request handlers in order. + Future> handleRequest( + Map request, + ) async { + var currentRequest = request; + for (final handler in handlers) { + currentRequest = await handler.handleRequest(currentRequest); + } + return currentRequest; + } + + /// Executes the response handlers in reverse order. + Future> handleResponse( + Map response, + ) async { + var currentResponse = response; + for (final handler in handlers.reversed) { + currentResponse = await handler.handleResponse(currentResponse); + } + return currentResponse; + } +} diff --git a/packages/a2a_dart/lib/src/client/http_transport.dart b/packages/a2a_dart/lib/src/client/http_transport.dart new file mode 100644 index 000000000..5780cefa9 --- /dev/null +++ b/packages/a2a_dart/lib/src/client/http_transport.dart @@ -0,0 +1,98 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:logging/logging.dart'; + +import 'a2a_exception.dart'; +import 'transport.dart'; + +/// An implementation of the [Transport] interface using standard HTTP requests. +/// +/// This transport is suitable for single-shot GET requests and POST requests +/// for non-streaming JSON-RPC calls. It does not support [sendStream]. +class HttpTransport implements Transport { + final String url; + + @override + final Map authHeaders; + + final http.Client client; + final Logger? log; + + HttpTransport({ + required this.url, + this.authHeaders = const {}, + http.Client? client, + this.log, + }) : client = client ?? http.Client(); + + @override + Future> get( + String path, { + Map headers = const {}, + }) async { + final uri = Uri.parse('$url$path'); + final allHeaders = {...authHeaders, ...headers}; + log?.fine('Sending GET request to $uri with headers: $allHeaders'); + try { + final response = await client.get(uri, headers: allHeaders); + log?.fine('Received response from GET $uri: ${response.body}'); + if (response.statusCode >= 400) { + throw A2AException.http( + statusCode: response.statusCode, + reason: response.reasonPhrase, + ); + } + return jsonDecode(response.body) as Map; + } on http.ClientException catch (e) { + throw A2AException.network(message: e.toString()); + } + } + + @override + Future> send( + Map request, { + String path = '', + }) async { + final uri = Uri.parse('$url$path'); + log?.fine('Sending POST request to $uri with body: $request'); + final allHeaders = {'Content-Type': 'application/json', ...authHeaders}; + try { + final response = await client.post( + uri, + headers: allHeaders, + body: jsonEncode(request), + ); + log?.fine('Received response from POST $uri: ${response.body}'); + if (response.statusCode >= 400) { + throw A2AException.http( + statusCode: response.statusCode, + reason: response.reasonPhrase, + ); + } + return jsonDecode(response.body) as Map; + } on http.ClientException catch (e) { + throw A2AException.network(message: e.toString()); + } on FormatException catch (e) { + throw A2AException.parsing(message: e.toString()); + } + } + + @override + Stream> sendStream(Map request) { + throw const A2AException.network( + message: + 'Streaming is not supported by HttpTransport. Use SseTransport ' + 'instead.', + ); + } + + @override + void close() { + client.close(); + } +} diff --git a/packages/a2a_dart/lib/src/client/sse_parser.dart b/packages/a2a_dart/lib/src/client/sse_parser.dart new file mode 100644 index 000000000..1ccd85551 --- /dev/null +++ b/packages/a2a_dart/lib/src/client/sse_parser.dart @@ -0,0 +1,74 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:logging/logging.dart'; + +import 'a2a_exception.dart'; + +/// A parser for Server-Sent Events (SSE). +/// +/// This class is responsible for parsing a stream of SSE lines and converting +/// them into a stream of JSON objects. It handles multi-line data, comments, +/// and JSON-RPC errors. +class SseParser { + /// The logger used for logging messages. + final Logger? log; + + /// Creates an [SseParser]. + SseParser({this.log}); + + /// Parses a stream of SSE lines and returns a stream of JSON objects. + Stream> parse(Stream lines) async* { + var data = []; + + try { + await for (final line in lines) { + log?.finer('Received SSE line: $line'); + if (line.startsWith('data:')) { + data.add(line.substring(5).trim()); + } else if (line.startsWith(':')) { + // Ignore comments (used for keepalives) + log?.finest('Ignoring SSE comment: $line'); + } else if (line.isEmpty) { + // Event boundary + if (data.isNotEmpty) { + final dataString = data.join('\n'); + data = []; // Clear for next event + if (dataString.isNotEmpty) { + try { + final jsonData = jsonDecode(dataString) as Map; + log?.finer('Parsed JSON: $jsonData'); + if (jsonData.containsKey('result')) { + final result = jsonData['result']; + if (result != null) { + yield result as Map; + } else { + log?.warning('Received a null result in the SSE stream.'); + } + } else if (jsonData.containsKey('error')) { + final error = jsonData['error'] as Map; + throw A2AException.jsonRpc( + code: error['code'] as int, + message: error['message'] as String, + data: error['data'] as Map?, + ); + } + } catch (e) { + throw A2AException.parsing(message: e.toString()); + } + } + } + } else { + log?.warning('Ignoring unexpected SSE line: $line'); + } + } + // ignore: avoid_catching_errors + } on StateError { + throw const A2AException.parsing(message: 'Stream closed unexpectedly.'); + } + } +} diff --git a/packages/a2a_dart/lib/src/client/sse_transport.dart b/packages/a2a_dart/lib/src/client/sse_transport.dart new file mode 100644 index 000000000..296fd4f7a --- /dev/null +++ b/packages/a2a_dart/lib/src/client/sse_transport.dart @@ -0,0 +1,78 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'package:logging/logging.dart'; +/// @docImport 'transport.dart'; +library; + +import 'dart:async'; +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +import 'a2a_exception.dart'; +import 'http_transport.dart'; +import 'sse_parser.dart'; + +/// A [Transport] implementation using Server-Sent Events (SSE) for streaming. +/// +/// This class extends [HttpTransport] to add support for streaming responses +/// from the server via an SSE connection. It should be used for methods like +/// `message/stream` where the server pushes multiple events over time. +class SseTransport extends HttpTransport { + /// Creates an [SseTransport] instance. + /// + /// Inherits parameters from [HttpTransport]: + /// - [url]: The base URL of the A2A server. + /// - [authHeaders]: Optional authentication headers. + /// - [client]: Optional [http.Client] for custom configurations or testing. + /// - [log]: Optional [Logger] instance. + SseTransport({ + required super.url, + super.authHeaders, + super.client, + super.log, + }); + + @override + Stream> sendStream(Map request) async* { + final uri = Uri.parse(url); + final body = jsonEncode(request); + log?.fine('Sending SSE request to $uri with body: $body'); + final allHeaders = { + 'Content-Type': 'application/json', + 'Accept': 'text/event-stream', + ...authHeaders, + }; + final httpRequest = http.Request('POST', uri) + ..headers.addAll(allHeaders) + ..body = body; + + try { + final response = await client.send(httpRequest); + if (response.statusCode >= 400) { + final responseBody = await response.stream.bytesToString(); + log?.severe( + 'Received error response: ${response.statusCode} $responseBody', + ); + throw A2AException.http( + statusCode: response.statusCode, + reason: '${response.reasonPhrase} $responseBody', + ); + } + final lines = response.stream + .transform(utf8.decoder) + .transform(const LineSplitter()); + yield* SseParser(log: log).parse(lines); + } on http.ClientException catch (e) { + throw A2AException.network(message: e.toString()); + } catch (e) { + if (e is A2AException) { + rethrow; + } + // Catch any other unexpected errors during stream processing. + throw A2AException.network(message: 'SSE stream error: $e'); + } + } +} diff --git a/packages/a2a_dart/lib/src/client/transport.dart b/packages/a2a_dart/lib/src/client/transport.dart new file mode 100644 index 000000000..0e021048d --- /dev/null +++ b/packages/a2a_dart/lib/src/client/transport.dart @@ -0,0 +1,68 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'a2a_client.dart'; +library; + +import 'dart:async'; + +/// Defines the contract for communication between an [A2AClient] and an A2A +/// server. +/// +/// Implementations of this interface handle the low-level details of sending +/// requests and receiving responses, potentially supporting different protocols +/// like HTTP, SSE, WebSockets, etc. +abstract class Transport { + /// Optional headers to be added to every request for authentication. + Map get authHeaders; + + /// Fetches a resource from the server using an HTTP GET request. + /// + /// This method is typically used for non-RPC interactions, such as retrieving + /// the agent card from `/.well-known/agent-card.json`. + /// + /// The [path] is appended to the base URL of the transport. Optional + /// [headers] can be provided for the request. + /// + /// Returns a [Future] that completes with the JSON-decoded response body as a + /// `Map`. Throws an `A2AException` if the request fails + /// (e.g., network error, non-200 status). + Future> get( + String path, { + Map headers = const {}, + }); + + /// Sends a single JSON-RPC request to the server, expecting a single + /// response. + /// + /// The [request] map must conform to the JSON-RPC 2.0 specification. The + /// [path] defaults to `/rpc`, the standard endpoint for A2A JSON-RPC calls. + /// + /// Returns a [Future] that completes with the JSON-decoded response body. The + /// structure of the response depends on whether the call was successful + /// (containing a `result`) or resulted in an error (containing an `error`). + /// Throws an `A2AException` for transport-level failures. + Future> send( + Map request, { + String path = '', + }); + + /// Sends a JSON-RPC request to the server and initiates a stream of + /// responses. + /// + /// This method is used for long-lived connections where the server can push + /// multiple messages to the client, such as Server-Sent Events (SSE). The + /// [request] map must conform to the JSON-RPC 2.0 specification. + /// + /// Returns a [Stream] of `Map`, where each map represents a + /// JSON object received from the server. The stream may emit `A2AException` + /// errors if issues occur during streaming. + Stream> sendStream(Map request); + + /// Closes the transport and releases any underlying resources. + /// + /// Implementations should handle graceful shutdown of connections, like + /// closing HTTP clients or WebSocket connections. + void close(); +} diff --git a/packages/a2a_dart/lib/src/core/agent_capabilities.dart b/packages/a2a_dart/lib/src/core/agent_capabilities.dart new file mode 100644 index 000000000..44f61a9c2 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_capabilities.dart @@ -0,0 +1,50 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'agent_card.dart'; +library; + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'agent_extension.dart'; + +part 'agent_capabilities.freezed.dart'; +part 'agent_capabilities.g.dart'; + +/// Describes the optional features and extensions an A2A agent supports. +/// +/// This class is part of the [AgentCard] and allows an agent to advertise +/// its capabilities to clients, such as support for streaming, push +/// notifications, and custom protocol extensions. +@freezed +abstract class AgentCapabilities with _$AgentCapabilities { + /// Creates an instance of [AgentCapabilities]. + /// + /// All parameters are optional and default to null if not provided, + /// indicating the capability is not specified. + const factory AgentCapabilities({ + /// Indicates if the agent supports streaming responses, typically via + /// Server-Sent Events (SSE). + /// + /// A value of `true` means the client can use methods like `message/stream`. + bool? streaming, + + /// Indicates if the agent supports sending push notifications for + /// asynchronous task updates to a client-specified endpoint. + bool? pushNotifications, + + /// Indicates if the agent maintains and can provide a history of state + /// transitions for tasks. + bool? stateTransitionHistory, + + /// A list of non-standard protocol extensions supported by the agent. + /// + /// See [AgentExtension] for more details. + List? extensions, + }) = _AgentCapabilities; + + /// Deserializes an [AgentCapabilities] instance from a JSON object. + factory AgentCapabilities.fromJson(Map json) => + _$AgentCapabilitiesFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/agent_capabilities.freezed.dart b/packages/a2a_dart/lib/src/core/agent_capabilities.freezed.dart new file mode 100644 index 000000000..a09ef6ec2 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_capabilities.freezed.dart @@ -0,0 +1,319 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'agent_capabilities.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$AgentCapabilities { + +/// Indicates if the agent supports streaming responses, typically via +/// Server-Sent Events (SSE). +/// +/// A value of `true` means the client can use methods like `message/stream`. + bool? get streaming;/// Indicates if the agent supports sending push notifications for +/// asynchronous task updates to a client-specified endpoint. + bool? get pushNotifications;/// Indicates if the agent maintains and can provide a history of state +/// transitions for tasks. + bool? get stateTransitionHistory;/// A list of non-standard protocol extensions supported by the agent. +/// +/// See [AgentExtension] for more details. + List? get extensions; +/// Create a copy of AgentCapabilities +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AgentCapabilitiesCopyWith get copyWith => _$AgentCapabilitiesCopyWithImpl(this as AgentCapabilities, _$identity); + + /// Serializes this AgentCapabilities to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AgentCapabilities&&(identical(other.streaming, streaming) || other.streaming == streaming)&&(identical(other.pushNotifications, pushNotifications) || other.pushNotifications == pushNotifications)&&(identical(other.stateTransitionHistory, stateTransitionHistory) || other.stateTransitionHistory == stateTransitionHistory)&&const DeepCollectionEquality().equals(other.extensions, extensions)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,streaming,pushNotifications,stateTransitionHistory,const DeepCollectionEquality().hash(extensions)); + +@override +String toString() { + return 'AgentCapabilities(streaming: $streaming, pushNotifications: $pushNotifications, stateTransitionHistory: $stateTransitionHistory, extensions: $extensions)'; +} + + +} + +/// @nodoc +abstract mixin class $AgentCapabilitiesCopyWith<$Res> { + factory $AgentCapabilitiesCopyWith(AgentCapabilities value, $Res Function(AgentCapabilities) _then) = _$AgentCapabilitiesCopyWithImpl; +@useResult +$Res call({ + bool? streaming, bool? pushNotifications, bool? stateTransitionHistory, List? extensions +}); + + + + +} +/// @nodoc +class _$AgentCapabilitiesCopyWithImpl<$Res> + implements $AgentCapabilitiesCopyWith<$Res> { + _$AgentCapabilitiesCopyWithImpl(this._self, this._then); + + final AgentCapabilities _self; + final $Res Function(AgentCapabilities) _then; + +/// Create a copy of AgentCapabilities +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? streaming = freezed,Object? pushNotifications = freezed,Object? stateTransitionHistory = freezed,Object? extensions = freezed,}) { + return _then(_self.copyWith( +streaming: freezed == streaming ? _self.streaming : streaming // ignore: cast_nullable_to_non_nullable +as bool?,pushNotifications: freezed == pushNotifications ? _self.pushNotifications : pushNotifications // ignore: cast_nullable_to_non_nullable +as bool?,stateTransitionHistory: freezed == stateTransitionHistory ? _self.stateTransitionHistory : stateTransitionHistory // ignore: cast_nullable_to_non_nullable +as bool?,extensions: freezed == extensions ? _self.extensions : extensions // ignore: cast_nullable_to_non_nullable +as List?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AgentCapabilities]. +extension AgentCapabilitiesPatterns on AgentCapabilities { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AgentCapabilities value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AgentCapabilities() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AgentCapabilities value) $default,){ +final _that = this; +switch (_that) { +case _AgentCapabilities(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AgentCapabilities value)? $default,){ +final _that = this; +switch (_that) { +case _AgentCapabilities() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( bool? streaming, bool? pushNotifications, bool? stateTransitionHistory, List? extensions)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AgentCapabilities() when $default != null: +return $default(_that.streaming,_that.pushNotifications,_that.stateTransitionHistory,_that.extensions);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( bool? streaming, bool? pushNotifications, bool? stateTransitionHistory, List? extensions) $default,) {final _that = this; +switch (_that) { +case _AgentCapabilities(): +return $default(_that.streaming,_that.pushNotifications,_that.stateTransitionHistory,_that.extensions);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool? streaming, bool? pushNotifications, bool? stateTransitionHistory, List? extensions)? $default,) {final _that = this; +switch (_that) { +case _AgentCapabilities() when $default != null: +return $default(_that.streaming,_that.pushNotifications,_that.stateTransitionHistory,_that.extensions);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AgentCapabilities implements AgentCapabilities { + const _AgentCapabilities({this.streaming, this.pushNotifications, this.stateTransitionHistory, final List? extensions}): _extensions = extensions; + factory _AgentCapabilities.fromJson(Map json) => _$AgentCapabilitiesFromJson(json); + +/// Indicates if the agent supports streaming responses, typically via +/// Server-Sent Events (SSE). +/// +/// A value of `true` means the client can use methods like `message/stream`. +@override final bool? streaming; +/// Indicates if the agent supports sending push notifications for +/// asynchronous task updates to a client-specified endpoint. +@override final bool? pushNotifications; +/// Indicates if the agent maintains and can provide a history of state +/// transitions for tasks. +@override final bool? stateTransitionHistory; +/// A list of non-standard protocol extensions supported by the agent. +/// +/// See [AgentExtension] for more details. + final List? _extensions; +/// A list of non-standard protocol extensions supported by the agent. +/// +/// See [AgentExtension] for more details. +@override List? get extensions { + final value = _extensions; + if (value == null) return null; + if (_extensions is EqualUnmodifiableListView) return _extensions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + + +/// Create a copy of AgentCapabilities +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AgentCapabilitiesCopyWith<_AgentCapabilities> get copyWith => __$AgentCapabilitiesCopyWithImpl<_AgentCapabilities>(this, _$identity); + +@override +Map toJson() { + return _$AgentCapabilitiesToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AgentCapabilities&&(identical(other.streaming, streaming) || other.streaming == streaming)&&(identical(other.pushNotifications, pushNotifications) || other.pushNotifications == pushNotifications)&&(identical(other.stateTransitionHistory, stateTransitionHistory) || other.stateTransitionHistory == stateTransitionHistory)&&const DeepCollectionEquality().equals(other._extensions, _extensions)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,streaming,pushNotifications,stateTransitionHistory,const DeepCollectionEquality().hash(_extensions)); + +@override +String toString() { + return 'AgentCapabilities(streaming: $streaming, pushNotifications: $pushNotifications, stateTransitionHistory: $stateTransitionHistory, extensions: $extensions)'; +} + + +} + +/// @nodoc +abstract mixin class _$AgentCapabilitiesCopyWith<$Res> implements $AgentCapabilitiesCopyWith<$Res> { + factory _$AgentCapabilitiesCopyWith(_AgentCapabilities value, $Res Function(_AgentCapabilities) _then) = __$AgentCapabilitiesCopyWithImpl; +@override @useResult +$Res call({ + bool? streaming, bool? pushNotifications, bool? stateTransitionHistory, List? extensions +}); + + + + +} +/// @nodoc +class __$AgentCapabilitiesCopyWithImpl<$Res> + implements _$AgentCapabilitiesCopyWith<$Res> { + __$AgentCapabilitiesCopyWithImpl(this._self, this._then); + + final _AgentCapabilities _self; + final $Res Function(_AgentCapabilities) _then; + +/// Create a copy of AgentCapabilities +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? streaming = freezed,Object? pushNotifications = freezed,Object? stateTransitionHistory = freezed,Object? extensions = freezed,}) { + return _then(_AgentCapabilities( +streaming: freezed == streaming ? _self.streaming : streaming // ignore: cast_nullable_to_non_nullable +as bool?,pushNotifications: freezed == pushNotifications ? _self.pushNotifications : pushNotifications // ignore: cast_nullable_to_non_nullable +as bool?,stateTransitionHistory: freezed == stateTransitionHistory ? _self.stateTransitionHistory : stateTransitionHistory // ignore: cast_nullable_to_non_nullable +as bool?,extensions: freezed == extensions ? _self._extensions : extensions // ignore: cast_nullable_to_non_nullable +as List?, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/agent_capabilities.g.dart b/packages/a2a_dart/lib/src/core/agent_capabilities.g.dart new file mode 100644 index 000000000..d928f410d --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_capabilities.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'agent_capabilities.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_AgentCapabilities _$AgentCapabilitiesFromJson(Map json) => + _AgentCapabilities( + streaming: json['streaming'] as bool?, + pushNotifications: json['pushNotifications'] as bool?, + stateTransitionHistory: json['stateTransitionHistory'] as bool?, + extensions: (json['extensions'] as List?) + ?.map((e) => AgentExtension.fromJson(e as Map)) + .toList(), + ); + +Map _$AgentCapabilitiesToJson(_AgentCapabilities instance) => + { + 'streaming': instance.streaming, + 'pushNotifications': instance.pushNotifications, + 'stateTransitionHistory': instance.stateTransitionHistory, + 'extensions': instance.extensions?.map((e) => e.toJson()).toList(), + }; diff --git a/packages/a2a_dart/lib/src/core/agent_card.dart b/packages/a2a_dart/lib/src/core/agent_card.dart new file mode 100644 index 000000000..534b43a0b --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_card.dart @@ -0,0 +1,113 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'agent_capabilities.dart'; +import 'agent_interface.dart'; +import 'agent_provider.dart'; +import 'agent_skill.dart'; +import 'security_scheme.dart'; + +part 'agent_card.freezed.dart'; +part 'agent_card.g.dart'; + +/// A self-describing manifest for an A2A agent. +/// +/// The [AgentCard] provides essential metadata about an agent, including its +/// identity, capabilities, skills, supported communication methods, and +/// security requirements. It serves as a primary discovery mechanism for +/// clients to understand how to interact with the agent, typically served from +/// `/.well-known/agent-card.json`. +@freezed +abstract class AgentCard with _$AgentCard { + /// Creates an [AgentCard] instance. + const factory AgentCard({ + /// The version of the A2A protocol that this agent implements. + /// + /// Example: "0.1.0". + required String protocolVersion, + + /// A human-readable name for the agent. + /// + /// Example: "Recipe Assistant". + required String name, + + /// A concise, human-readable description of the agent's purpose and + /// functionality. + required String description, + + /// The primary endpoint URL for interacting with the agent. + required String url, + + /// The transport protocol used by the primary endpoint specified in [url]. + /// + /// Defaults to [TransportProtocol.jsonrpc] if not specified. + TransportProtocol? preferredTransport, + + /// A list of alternative interfaces the agent supports. + /// + /// This allows an agent to expose its API via multiple transport protocols + /// or at different URLs. + List? additionalInterfaces, + + /// An optional URL pointing to an icon representing the agent. + String? iconUrl, + + /// Information about the entity providing the agent service. + AgentProvider? provider, + + /// The version string of the agent implementation itself. + /// + /// The format is specific to the agent provider. + required String version, + + /// An optional URL pointing to human-readable documentation for the agent. + String? documentationUrl, + + /// A declaration of optional A2A protocol features and extensions + /// supported by the agent. + required AgentCapabilities capabilities, + + /// A map of security schemes supported by the agent for authorization. + /// + /// The keys are scheme names (e.g., "apiKey", "bearerAuth") which can be + /// referenced in security requirements. The values define the scheme + /// details, following the OpenAPI 3.0 Security Scheme Object structure. + Map? securitySchemes, + + /// A list of security requirements that apply globally to all interactions + /// with this agent, unless overridden by a specific skill or method. + /// + /// Each item in the list is a map representing a disjunction (OR) of + /// security schemes. Within each map, the keys are scheme names from + /// [securitySchemes], and the values are lists of required scopes (AND). + List>>? security, + + /// Default set of supported input MIME types (e.g., "text/plain") for all + /// skills. + /// + /// This can be overridden on a per-skill basis in [AgentSkill]. + required List defaultInputModes, + + /// Default set of supported output MIME types (e.g., "application/json") for + /// all skills. + /// + /// This can be overridden on a per-skill basis in [AgentSkill]. + required List defaultOutputModes, + + /// The set of skills (distinct functionalities) that the agent can perform. + required List skills, + + /// Indicates whether the agent can provide an extended agent card with + /// potentially more details to authenticated users. + /// + /// Defaults to `false` if not specified. + bool? supportsAuthenticatedExtendedCard, + }) = _AgentCard; + + /// Deserializes an [AgentCard] instance from a JSON object. + factory AgentCard.fromJson(Map json) => + _$AgentCardFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/agent_card.freezed.dart b/packages/a2a_dart/lib/src/core/agent_card.freezed.dart new file mode 100644 index 000000000..23d02aaad --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_card.freezed.dart @@ -0,0 +1,529 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'agent_card.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$AgentCard { + +/// The version of the A2A protocol that this agent implements. +/// +/// Example: "0.1.0". + String get protocolVersion;/// A human-readable name for the agent. +/// +/// Example: "Recipe Assistant". + String get name;/// A concise, human-readable description of the agent's purpose and +/// functionality. + String get description;/// The primary endpoint URL for interacting with the agent. + String get url;/// The transport protocol used by the primary endpoint specified in [url]. +/// +/// Defaults to [TransportProtocol.jsonrpc] if not specified. + TransportProtocol? get preferredTransport;/// A list of alternative interfaces the agent supports. +/// +/// This allows an agent to expose its API via multiple transport protocols +/// or at different URLs. + List? get additionalInterfaces;/// An optional URL pointing to an icon representing the agent. + String? get iconUrl;/// Information about the entity providing the agent service. + AgentProvider? get provider;/// The version string of the agent implementation itself. +/// +/// The format is specific to the agent provider. + String get version;/// An optional URL pointing to human-readable documentation for the agent. + String? get documentationUrl;/// A declaration of optional A2A protocol features and extensions +/// supported by the agent. + AgentCapabilities get capabilities;/// A map of security schemes supported by the agent for authorization. +/// +/// The keys are scheme names (e.g., "apiKey", "bearerAuth") which can be +/// referenced in security requirements. The values define the scheme +/// details, following the OpenAPI 3.0 Security Scheme Object structure. + Map? get securitySchemes;/// A list of security requirements that apply globally to all interactions +/// with this agent, unless overridden by a specific skill or method. +/// +/// Each item in the list is a map representing a disjunction (OR) of +/// security schemes. Within each map, the keys are scheme names from +/// [securitySchemes], and the values are lists of required scopes (AND). + List>>? get security;/// Default set of supported input MIME types (e.g., "text/plain") for all +/// skills. +/// +/// This can be overridden on a per-skill basis in [AgentSkill]. + List get defaultInputModes;/// Default set of supported output MIME types (e.g., "application/json") for +/// all skills. +/// +/// This can be overridden on a per-skill basis in [AgentSkill]. + List get defaultOutputModes;/// The set of skills (distinct functionalities) that the agent can perform. + List get skills;/// Indicates whether the agent can provide an extended agent card with +/// potentially more details to authenticated users. +/// +/// Defaults to `false` if not specified. + bool? get supportsAuthenticatedExtendedCard; +/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AgentCardCopyWith get copyWith => _$AgentCardCopyWithImpl(this as AgentCard, _$identity); + + /// Serializes this AgentCard to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AgentCard&&(identical(other.protocolVersion, protocolVersion) || other.protocolVersion == protocolVersion)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.url, url) || other.url == url)&&(identical(other.preferredTransport, preferredTransport) || other.preferredTransport == preferredTransport)&&const DeepCollectionEquality().equals(other.additionalInterfaces, additionalInterfaces)&&(identical(other.iconUrl, iconUrl) || other.iconUrl == iconUrl)&&(identical(other.provider, provider) || other.provider == provider)&&(identical(other.version, version) || other.version == version)&&(identical(other.documentationUrl, documentationUrl) || other.documentationUrl == documentationUrl)&&(identical(other.capabilities, capabilities) || other.capabilities == capabilities)&&const DeepCollectionEquality().equals(other.securitySchemes, securitySchemes)&&const DeepCollectionEquality().equals(other.security, security)&&const DeepCollectionEquality().equals(other.defaultInputModes, defaultInputModes)&&const DeepCollectionEquality().equals(other.defaultOutputModes, defaultOutputModes)&&const DeepCollectionEquality().equals(other.skills, skills)&&(identical(other.supportsAuthenticatedExtendedCard, supportsAuthenticatedExtendedCard) || other.supportsAuthenticatedExtendedCard == supportsAuthenticatedExtendedCard)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,protocolVersion,name,description,url,preferredTransport,const DeepCollectionEquality().hash(additionalInterfaces),iconUrl,provider,version,documentationUrl,capabilities,const DeepCollectionEquality().hash(securitySchemes),const DeepCollectionEquality().hash(security),const DeepCollectionEquality().hash(defaultInputModes),const DeepCollectionEquality().hash(defaultOutputModes),const DeepCollectionEquality().hash(skills),supportsAuthenticatedExtendedCard); + +@override +String toString() { + return 'AgentCard(protocolVersion: $protocolVersion, name: $name, description: $description, url: $url, preferredTransport: $preferredTransport, additionalInterfaces: $additionalInterfaces, iconUrl: $iconUrl, provider: $provider, version: $version, documentationUrl: $documentationUrl, capabilities: $capabilities, securitySchemes: $securitySchemes, security: $security, defaultInputModes: $defaultInputModes, defaultOutputModes: $defaultOutputModes, skills: $skills, supportsAuthenticatedExtendedCard: $supportsAuthenticatedExtendedCard)'; +} + + +} + +/// @nodoc +abstract mixin class $AgentCardCopyWith<$Res> { + factory $AgentCardCopyWith(AgentCard value, $Res Function(AgentCard) _then) = _$AgentCardCopyWithImpl; +@useResult +$Res call({ + String protocolVersion, String name, String description, String url, TransportProtocol? preferredTransport, List? additionalInterfaces, String? iconUrl, AgentProvider? provider, String version, String? documentationUrl, AgentCapabilities capabilities, Map? securitySchemes, List>>? security, List defaultInputModes, List defaultOutputModes, List skills, bool? supportsAuthenticatedExtendedCard +}); + + +$AgentProviderCopyWith<$Res>? get provider;$AgentCapabilitiesCopyWith<$Res> get capabilities; + +} +/// @nodoc +class _$AgentCardCopyWithImpl<$Res> + implements $AgentCardCopyWith<$Res> { + _$AgentCardCopyWithImpl(this._self, this._then); + + final AgentCard _self; + final $Res Function(AgentCard) _then; + +/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? protocolVersion = null,Object? name = null,Object? description = null,Object? url = null,Object? preferredTransport = freezed,Object? additionalInterfaces = freezed,Object? iconUrl = freezed,Object? provider = freezed,Object? version = null,Object? documentationUrl = freezed,Object? capabilities = null,Object? securitySchemes = freezed,Object? security = freezed,Object? defaultInputModes = null,Object? defaultOutputModes = null,Object? skills = null,Object? supportsAuthenticatedExtendedCard = freezed,}) { + return _then(_self.copyWith( +protocolVersion: null == protocolVersion ? _self.protocolVersion : protocolVersion // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String,preferredTransport: freezed == preferredTransport ? _self.preferredTransport : preferredTransport // ignore: cast_nullable_to_non_nullable +as TransportProtocol?,additionalInterfaces: freezed == additionalInterfaces ? _self.additionalInterfaces : additionalInterfaces // ignore: cast_nullable_to_non_nullable +as List?,iconUrl: freezed == iconUrl ? _self.iconUrl : iconUrl // ignore: cast_nullable_to_non_nullable +as String?,provider: freezed == provider ? _self.provider : provider // ignore: cast_nullable_to_non_nullable +as AgentProvider?,version: null == version ? _self.version : version // ignore: cast_nullable_to_non_nullable +as String,documentationUrl: freezed == documentationUrl ? _self.documentationUrl : documentationUrl // ignore: cast_nullable_to_non_nullable +as String?,capabilities: null == capabilities ? _self.capabilities : capabilities // ignore: cast_nullable_to_non_nullable +as AgentCapabilities,securitySchemes: freezed == securitySchemes ? _self.securitySchemes : securitySchemes // ignore: cast_nullable_to_non_nullable +as Map?,security: freezed == security ? _self.security : security // ignore: cast_nullable_to_non_nullable +as List>>?,defaultInputModes: null == defaultInputModes ? _self.defaultInputModes : defaultInputModes // ignore: cast_nullable_to_non_nullable +as List,defaultOutputModes: null == defaultOutputModes ? _self.defaultOutputModes : defaultOutputModes // ignore: cast_nullable_to_non_nullable +as List,skills: null == skills ? _self.skills : skills // ignore: cast_nullable_to_non_nullable +as List,supportsAuthenticatedExtendedCard: freezed == supportsAuthenticatedExtendedCard ? _self.supportsAuthenticatedExtendedCard : supportsAuthenticatedExtendedCard // ignore: cast_nullable_to_non_nullable +as bool?, + )); +} +/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$AgentProviderCopyWith<$Res>? get provider { + if (_self.provider == null) { + return null; + } + + return $AgentProviderCopyWith<$Res>(_self.provider!, (value) { + return _then(_self.copyWith(provider: value)); + }); +}/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$AgentCapabilitiesCopyWith<$Res> get capabilities { + + return $AgentCapabilitiesCopyWith<$Res>(_self.capabilities, (value) { + return _then(_self.copyWith(capabilities: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [AgentCard]. +extension AgentCardPatterns on AgentCard { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AgentCard value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AgentCard() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AgentCard value) $default,){ +final _that = this; +switch (_that) { +case _AgentCard(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AgentCard value)? $default,){ +final _that = this; +switch (_that) { +case _AgentCard() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String protocolVersion, String name, String description, String url, TransportProtocol? preferredTransport, List? additionalInterfaces, String? iconUrl, AgentProvider? provider, String version, String? documentationUrl, AgentCapabilities capabilities, Map? securitySchemes, List>>? security, List defaultInputModes, List defaultOutputModes, List skills, bool? supportsAuthenticatedExtendedCard)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AgentCard() when $default != null: +return $default(_that.protocolVersion,_that.name,_that.description,_that.url,_that.preferredTransport,_that.additionalInterfaces,_that.iconUrl,_that.provider,_that.version,_that.documentationUrl,_that.capabilities,_that.securitySchemes,_that.security,_that.defaultInputModes,_that.defaultOutputModes,_that.skills,_that.supportsAuthenticatedExtendedCard);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String protocolVersion, String name, String description, String url, TransportProtocol? preferredTransport, List? additionalInterfaces, String? iconUrl, AgentProvider? provider, String version, String? documentationUrl, AgentCapabilities capabilities, Map? securitySchemes, List>>? security, List defaultInputModes, List defaultOutputModes, List skills, bool? supportsAuthenticatedExtendedCard) $default,) {final _that = this; +switch (_that) { +case _AgentCard(): +return $default(_that.protocolVersion,_that.name,_that.description,_that.url,_that.preferredTransport,_that.additionalInterfaces,_that.iconUrl,_that.provider,_that.version,_that.documentationUrl,_that.capabilities,_that.securitySchemes,_that.security,_that.defaultInputModes,_that.defaultOutputModes,_that.skills,_that.supportsAuthenticatedExtendedCard);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String protocolVersion, String name, String description, String url, TransportProtocol? preferredTransport, List? additionalInterfaces, String? iconUrl, AgentProvider? provider, String version, String? documentationUrl, AgentCapabilities capabilities, Map? securitySchemes, List>>? security, List defaultInputModes, List defaultOutputModes, List skills, bool? supportsAuthenticatedExtendedCard)? $default,) {final _that = this; +switch (_that) { +case _AgentCard() when $default != null: +return $default(_that.protocolVersion,_that.name,_that.description,_that.url,_that.preferredTransport,_that.additionalInterfaces,_that.iconUrl,_that.provider,_that.version,_that.documentationUrl,_that.capabilities,_that.securitySchemes,_that.security,_that.defaultInputModes,_that.defaultOutputModes,_that.skills,_that.supportsAuthenticatedExtendedCard);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AgentCard implements AgentCard { + const _AgentCard({required this.protocolVersion, required this.name, required this.description, required this.url, this.preferredTransport, final List? additionalInterfaces, this.iconUrl, this.provider, required this.version, this.documentationUrl, required this.capabilities, final Map? securitySchemes, final List>>? security, required final List defaultInputModes, required final List defaultOutputModes, required final List skills, this.supportsAuthenticatedExtendedCard}): _additionalInterfaces = additionalInterfaces,_securitySchemes = securitySchemes,_security = security,_defaultInputModes = defaultInputModes,_defaultOutputModes = defaultOutputModes,_skills = skills; + factory _AgentCard.fromJson(Map json) => _$AgentCardFromJson(json); + +/// The version of the A2A protocol that this agent implements. +/// +/// Example: "0.1.0". +@override final String protocolVersion; +/// A human-readable name for the agent. +/// +/// Example: "Recipe Assistant". +@override final String name; +/// A concise, human-readable description of the agent's purpose and +/// functionality. +@override final String description; +/// The primary endpoint URL for interacting with the agent. +@override final String url; +/// The transport protocol used by the primary endpoint specified in [url]. +/// +/// Defaults to [TransportProtocol.jsonrpc] if not specified. +@override final TransportProtocol? preferredTransport; +/// A list of alternative interfaces the agent supports. +/// +/// This allows an agent to expose its API via multiple transport protocols +/// or at different URLs. + final List? _additionalInterfaces; +/// A list of alternative interfaces the agent supports. +/// +/// This allows an agent to expose its API via multiple transport protocols +/// or at different URLs. +@override List? get additionalInterfaces { + final value = _additionalInterfaces; + if (value == null) return null; + if (_additionalInterfaces is EqualUnmodifiableListView) return _additionalInterfaces; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// An optional URL pointing to an icon representing the agent. +@override final String? iconUrl; +/// Information about the entity providing the agent service. +@override final AgentProvider? provider; +/// The version string of the agent implementation itself. +/// +/// The format is specific to the agent provider. +@override final String version; +/// An optional URL pointing to human-readable documentation for the agent. +@override final String? documentationUrl; +/// A declaration of optional A2A protocol features and extensions +/// supported by the agent. +@override final AgentCapabilities capabilities; +/// A map of security schemes supported by the agent for authorization. +/// +/// The keys are scheme names (e.g., "apiKey", "bearerAuth") which can be +/// referenced in security requirements. The values define the scheme +/// details, following the OpenAPI 3.0 Security Scheme Object structure. + final Map? _securitySchemes; +/// A map of security schemes supported by the agent for authorization. +/// +/// The keys are scheme names (e.g., "apiKey", "bearerAuth") which can be +/// referenced in security requirements. The values define the scheme +/// details, following the OpenAPI 3.0 Security Scheme Object structure. +@override Map? get securitySchemes { + final value = _securitySchemes; + if (value == null) return null; + if (_securitySchemes is EqualUnmodifiableMapView) return _securitySchemes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + +/// A list of security requirements that apply globally to all interactions +/// with this agent, unless overridden by a specific skill or method. +/// +/// Each item in the list is a map representing a disjunction (OR) of +/// security schemes. Within each map, the keys are scheme names from +/// [securitySchemes], and the values are lists of required scopes (AND). + final List>>? _security; +/// A list of security requirements that apply globally to all interactions +/// with this agent, unless overridden by a specific skill or method. +/// +/// Each item in the list is a map representing a disjunction (OR) of +/// security schemes. Within each map, the keys are scheme names from +/// [securitySchemes], and the values are lists of required scopes (AND). +@override List>>? get security { + final value = _security; + if (value == null) return null; + if (_security is EqualUnmodifiableListView) return _security; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// Default set of supported input MIME types (e.g., "text/plain") for all +/// skills. +/// +/// This can be overridden on a per-skill basis in [AgentSkill]. + final List _defaultInputModes; +/// Default set of supported input MIME types (e.g., "text/plain") for all +/// skills. +/// +/// This can be overridden on a per-skill basis in [AgentSkill]. +@override List get defaultInputModes { + if (_defaultInputModes is EqualUnmodifiableListView) return _defaultInputModes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_defaultInputModes); +} + +/// Default set of supported output MIME types (e.g., "application/json") for +/// all skills. +/// +/// This can be overridden on a per-skill basis in [AgentSkill]. + final List _defaultOutputModes; +/// Default set of supported output MIME types (e.g., "application/json") for +/// all skills. +/// +/// This can be overridden on a per-skill basis in [AgentSkill]. +@override List get defaultOutputModes { + if (_defaultOutputModes is EqualUnmodifiableListView) return _defaultOutputModes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_defaultOutputModes); +} + +/// The set of skills (distinct functionalities) that the agent can perform. + final List _skills; +/// The set of skills (distinct functionalities) that the agent can perform. +@override List get skills { + if (_skills is EqualUnmodifiableListView) return _skills; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_skills); +} + +/// Indicates whether the agent can provide an extended agent card with +/// potentially more details to authenticated users. +/// +/// Defaults to `false` if not specified. +@override final bool? supportsAuthenticatedExtendedCard; + +/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AgentCardCopyWith<_AgentCard> get copyWith => __$AgentCardCopyWithImpl<_AgentCard>(this, _$identity); + +@override +Map toJson() { + return _$AgentCardToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AgentCard&&(identical(other.protocolVersion, protocolVersion) || other.protocolVersion == protocolVersion)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.url, url) || other.url == url)&&(identical(other.preferredTransport, preferredTransport) || other.preferredTransport == preferredTransport)&&const DeepCollectionEquality().equals(other._additionalInterfaces, _additionalInterfaces)&&(identical(other.iconUrl, iconUrl) || other.iconUrl == iconUrl)&&(identical(other.provider, provider) || other.provider == provider)&&(identical(other.version, version) || other.version == version)&&(identical(other.documentationUrl, documentationUrl) || other.documentationUrl == documentationUrl)&&(identical(other.capabilities, capabilities) || other.capabilities == capabilities)&&const DeepCollectionEquality().equals(other._securitySchemes, _securitySchemes)&&const DeepCollectionEquality().equals(other._security, _security)&&const DeepCollectionEquality().equals(other._defaultInputModes, _defaultInputModes)&&const DeepCollectionEquality().equals(other._defaultOutputModes, _defaultOutputModes)&&const DeepCollectionEquality().equals(other._skills, _skills)&&(identical(other.supportsAuthenticatedExtendedCard, supportsAuthenticatedExtendedCard) || other.supportsAuthenticatedExtendedCard == supportsAuthenticatedExtendedCard)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,protocolVersion,name,description,url,preferredTransport,const DeepCollectionEquality().hash(_additionalInterfaces),iconUrl,provider,version,documentationUrl,capabilities,const DeepCollectionEquality().hash(_securitySchemes),const DeepCollectionEquality().hash(_security),const DeepCollectionEquality().hash(_defaultInputModes),const DeepCollectionEquality().hash(_defaultOutputModes),const DeepCollectionEquality().hash(_skills),supportsAuthenticatedExtendedCard); + +@override +String toString() { + return 'AgentCard(protocolVersion: $protocolVersion, name: $name, description: $description, url: $url, preferredTransport: $preferredTransport, additionalInterfaces: $additionalInterfaces, iconUrl: $iconUrl, provider: $provider, version: $version, documentationUrl: $documentationUrl, capabilities: $capabilities, securitySchemes: $securitySchemes, security: $security, defaultInputModes: $defaultInputModes, defaultOutputModes: $defaultOutputModes, skills: $skills, supportsAuthenticatedExtendedCard: $supportsAuthenticatedExtendedCard)'; +} + + +} + +/// @nodoc +abstract mixin class _$AgentCardCopyWith<$Res> implements $AgentCardCopyWith<$Res> { + factory _$AgentCardCopyWith(_AgentCard value, $Res Function(_AgentCard) _then) = __$AgentCardCopyWithImpl; +@override @useResult +$Res call({ + String protocolVersion, String name, String description, String url, TransportProtocol? preferredTransport, List? additionalInterfaces, String? iconUrl, AgentProvider? provider, String version, String? documentationUrl, AgentCapabilities capabilities, Map? securitySchemes, List>>? security, List defaultInputModes, List defaultOutputModes, List skills, bool? supportsAuthenticatedExtendedCard +}); + + +@override $AgentProviderCopyWith<$Res>? get provider;@override $AgentCapabilitiesCopyWith<$Res> get capabilities; + +} +/// @nodoc +class __$AgentCardCopyWithImpl<$Res> + implements _$AgentCardCopyWith<$Res> { + __$AgentCardCopyWithImpl(this._self, this._then); + + final _AgentCard _self; + final $Res Function(_AgentCard) _then; + +/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? protocolVersion = null,Object? name = null,Object? description = null,Object? url = null,Object? preferredTransport = freezed,Object? additionalInterfaces = freezed,Object? iconUrl = freezed,Object? provider = freezed,Object? version = null,Object? documentationUrl = freezed,Object? capabilities = null,Object? securitySchemes = freezed,Object? security = freezed,Object? defaultInputModes = null,Object? defaultOutputModes = null,Object? skills = null,Object? supportsAuthenticatedExtendedCard = freezed,}) { + return _then(_AgentCard( +protocolVersion: null == protocolVersion ? _self.protocolVersion : protocolVersion // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String,preferredTransport: freezed == preferredTransport ? _self.preferredTransport : preferredTransport // ignore: cast_nullable_to_non_nullable +as TransportProtocol?,additionalInterfaces: freezed == additionalInterfaces ? _self._additionalInterfaces : additionalInterfaces // ignore: cast_nullable_to_non_nullable +as List?,iconUrl: freezed == iconUrl ? _self.iconUrl : iconUrl // ignore: cast_nullable_to_non_nullable +as String?,provider: freezed == provider ? _self.provider : provider // ignore: cast_nullable_to_non_nullable +as AgentProvider?,version: null == version ? _self.version : version // ignore: cast_nullable_to_non_nullable +as String,documentationUrl: freezed == documentationUrl ? _self.documentationUrl : documentationUrl // ignore: cast_nullable_to_non_nullable +as String?,capabilities: null == capabilities ? _self.capabilities : capabilities // ignore: cast_nullable_to_non_nullable +as AgentCapabilities,securitySchemes: freezed == securitySchemes ? _self._securitySchemes : securitySchemes // ignore: cast_nullable_to_non_nullable +as Map?,security: freezed == security ? _self._security : security // ignore: cast_nullable_to_non_nullable +as List>>?,defaultInputModes: null == defaultInputModes ? _self._defaultInputModes : defaultInputModes // ignore: cast_nullable_to_non_nullable +as List,defaultOutputModes: null == defaultOutputModes ? _self._defaultOutputModes : defaultOutputModes // ignore: cast_nullable_to_non_nullable +as List,skills: null == skills ? _self._skills : skills // ignore: cast_nullable_to_non_nullable +as List,supportsAuthenticatedExtendedCard: freezed == supportsAuthenticatedExtendedCard ? _self.supportsAuthenticatedExtendedCard : supportsAuthenticatedExtendedCard // ignore: cast_nullable_to_non_nullable +as bool?, + )); +} + +/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$AgentProviderCopyWith<$Res>? get provider { + if (_self.provider == null) { + return null; + } + + return $AgentProviderCopyWith<$Res>(_self.provider!, (value) { + return _then(_self.copyWith(provider: value)); + }); +}/// Create a copy of AgentCard +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$AgentCapabilitiesCopyWith<$Res> get capabilities { + + return $AgentCapabilitiesCopyWith<$Res>(_self.capabilities, (value) { + return _then(_self.copyWith(capabilities: value)); + }); +} +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/agent_card.g.dart b/packages/a2a_dart/lib/src/core/agent_card.g.dart new file mode 100644 index 000000000..5011e365f --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_card.g.dart @@ -0,0 +1,87 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'agent_card.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_AgentCard _$AgentCardFromJson(Map json) => _AgentCard( + protocolVersion: json['protocolVersion'] as String, + name: json['name'] as String, + description: json['description'] as String, + url: json['url'] as String, + preferredTransport: $enumDecodeNullable( + _$TransportProtocolEnumMap, + json['preferredTransport'], + ), + additionalInterfaces: (json['additionalInterfaces'] as List?) + ?.map((e) => AgentInterface.fromJson(e as Map)) + .toList(), + iconUrl: json['iconUrl'] as String?, + provider: json['provider'] == null + ? null + : AgentProvider.fromJson(json['provider'] as Map), + version: json['version'] as String, + documentationUrl: json['documentationUrl'] as String?, + capabilities: AgentCapabilities.fromJson( + json['capabilities'] as Map, + ), + securitySchemes: (json['securitySchemes'] as Map?)?.map( + (k, e) => MapEntry(k, SecurityScheme.fromJson(e as Map)), + ), + security: (json['security'] as List?) + ?.map( + (e) => (e as Map).map( + (k, e) => MapEntry( + k, + (e as List).map((e) => e as String).toList(), + ), + ), + ) + .toList(), + defaultInputModes: (json['defaultInputModes'] as List) + .map((e) => e as String) + .toList(), + defaultOutputModes: (json['defaultOutputModes'] as List) + .map((e) => e as String) + .toList(), + skills: (json['skills'] as List) + .map((e) => AgentSkill.fromJson(e as Map)) + .toList(), + supportsAuthenticatedExtendedCard: + json['supportsAuthenticatedExtendedCard'] as bool?, +); + +Map _$AgentCardToJson( + _AgentCard instance, +) => { + 'protocolVersion': instance.protocolVersion, + 'name': instance.name, + 'description': instance.description, + 'url': instance.url, + 'preferredTransport': _$TransportProtocolEnumMap[instance.preferredTransport], + 'additionalInterfaces': instance.additionalInterfaces + ?.map((e) => e.toJson()) + .toList(), + 'iconUrl': instance.iconUrl, + 'provider': instance.provider?.toJson(), + 'version': instance.version, + 'documentationUrl': instance.documentationUrl, + 'capabilities': instance.capabilities.toJson(), + 'securitySchemes': instance.securitySchemes?.map( + (k, e) => MapEntry(k, e.toJson()), + ), + 'security': instance.security, + 'defaultInputModes': instance.defaultInputModes, + 'defaultOutputModes': instance.defaultOutputModes, + 'skills': instance.skills.map((e) => e.toJson()).toList(), + 'supportsAuthenticatedExtendedCard': + instance.supportsAuthenticatedExtendedCard, +}; + +const _$TransportProtocolEnumMap = { + TransportProtocol.jsonrpc: 'JSONRPC', + TransportProtocol.grpc: 'GRPC', + TransportProtocol.httpJson: 'HTTP+JSON', +}; diff --git a/packages/a2a_dart/lib/src/core/agent_extension.dart b/packages/a2a_dart/lib/src/core/agent_extension.dart new file mode 100644 index 000000000..84cdb1635 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_extension.dart @@ -0,0 +1,38 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'agent_capabilities.dart'; +library; + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'agent_extension.freezed.dart'; +part 'agent_extension.g.dart'; + +/// Specifies an extension to the A2A protocol supported by an agent. +/// +/// Used in [AgentCapabilities] to list supported protocol extensions, allowing +/// agents to advertise custom features beyond the core A2A specification. +@freezed +abstract class AgentExtension with _$AgentExtension { + /// Creates an [AgentExtension]. + const factory AgentExtension({ + /// The unique URI identifying the extension. + required String uri, + + /// A human-readable description of the extension. + String? description, + + /// If true, the client must understand and comply with the extension's + /// requirements to interact with the agent. + bool? required, + + /// Optional, extension-specific configuration parameters. + Map? params, + }) = _AgentExtension; + + /// Creates an [AgentExtension] from a JSON object. + factory AgentExtension.fromJson(Map json) => + _$AgentExtensionFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/agent_extension.freezed.dart b/packages/a2a_dart/lib/src/core/agent_extension.freezed.dart new file mode 100644 index 000000000..1e6da723a --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_extension.freezed.dart @@ -0,0 +1,305 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'agent_extension.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$AgentExtension { + +/// The unique URI identifying the extension. + String get uri;/// A human-readable description of the extension. + String? get description;/// If true, the client must understand and comply with the extension's +/// requirements to interact with the agent. + bool? get required;/// Optional, extension-specific configuration parameters. + Map? get params; +/// Create a copy of AgentExtension +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AgentExtensionCopyWith get copyWith => _$AgentExtensionCopyWithImpl(this as AgentExtension, _$identity); + + /// Serializes this AgentExtension to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AgentExtension&&(identical(other.uri, uri) || other.uri == uri)&&(identical(other.description, description) || other.description == description)&&(identical(other.required, required) || other.required == required)&&const DeepCollectionEquality().equals(other.params, params)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,uri,description,required,const DeepCollectionEquality().hash(params)); + +@override +String toString() { + return 'AgentExtension(uri: $uri, description: $description, required: $required, params: $params)'; +} + + +} + +/// @nodoc +abstract mixin class $AgentExtensionCopyWith<$Res> { + factory $AgentExtensionCopyWith(AgentExtension value, $Res Function(AgentExtension) _then) = _$AgentExtensionCopyWithImpl; +@useResult +$Res call({ + String uri, String? description, bool? required, Map? params +}); + + + + +} +/// @nodoc +class _$AgentExtensionCopyWithImpl<$Res> + implements $AgentExtensionCopyWith<$Res> { + _$AgentExtensionCopyWithImpl(this._self, this._then); + + final AgentExtension _self; + final $Res Function(AgentExtension) _then; + +/// Create a copy of AgentExtension +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? uri = null,Object? description = freezed,Object? required = freezed,Object? params = freezed,}) { + return _then(_self.copyWith( +uri: null == uri ? _self.uri : uri // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable +as bool?,params: freezed == params ? _self.params : params // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AgentExtension]. +extension AgentExtensionPatterns on AgentExtension { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AgentExtension value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AgentExtension() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AgentExtension value) $default,){ +final _that = this; +switch (_that) { +case _AgentExtension(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AgentExtension value)? $default,){ +final _that = this; +switch (_that) { +case _AgentExtension() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String uri, String? description, bool? required, Map? params)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AgentExtension() when $default != null: +return $default(_that.uri,_that.description,_that.required,_that.params);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String uri, String? description, bool? required, Map? params) $default,) {final _that = this; +switch (_that) { +case _AgentExtension(): +return $default(_that.uri,_that.description,_that.required,_that.params);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String uri, String? description, bool? required, Map? params)? $default,) {final _that = this; +switch (_that) { +case _AgentExtension() when $default != null: +return $default(_that.uri,_that.description,_that.required,_that.params);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AgentExtension implements AgentExtension { + const _AgentExtension({required this.uri, this.description, this.required, final Map? params}): _params = params; + factory _AgentExtension.fromJson(Map json) => _$AgentExtensionFromJson(json); + +/// The unique URI identifying the extension. +@override final String uri; +/// A human-readable description of the extension. +@override final String? description; +/// If true, the client must understand and comply with the extension's +/// requirements to interact with the agent. +@override final bool? required; +/// Optional, extension-specific configuration parameters. + final Map? _params; +/// Optional, extension-specific configuration parameters. +@override Map? get params { + final value = _params; + if (value == null) return null; + if (_params is EqualUnmodifiableMapView) return _params; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +/// Create a copy of AgentExtension +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AgentExtensionCopyWith<_AgentExtension> get copyWith => __$AgentExtensionCopyWithImpl<_AgentExtension>(this, _$identity); + +@override +Map toJson() { + return _$AgentExtensionToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AgentExtension&&(identical(other.uri, uri) || other.uri == uri)&&(identical(other.description, description) || other.description == description)&&(identical(other.required, required) || other.required == required)&&const DeepCollectionEquality().equals(other._params, _params)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,uri,description,required,const DeepCollectionEquality().hash(_params)); + +@override +String toString() { + return 'AgentExtension(uri: $uri, description: $description, required: $required, params: $params)'; +} + + +} + +/// @nodoc +abstract mixin class _$AgentExtensionCopyWith<$Res> implements $AgentExtensionCopyWith<$Res> { + factory _$AgentExtensionCopyWith(_AgentExtension value, $Res Function(_AgentExtension) _then) = __$AgentExtensionCopyWithImpl; +@override @useResult +$Res call({ + String uri, String? description, bool? required, Map? params +}); + + + + +} +/// @nodoc +class __$AgentExtensionCopyWithImpl<$Res> + implements _$AgentExtensionCopyWith<$Res> { + __$AgentExtensionCopyWithImpl(this._self, this._then); + + final _AgentExtension _self; + final $Res Function(_AgentExtension) _then; + +/// Create a copy of AgentExtension +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? uri = null,Object? description = freezed,Object? required = freezed,Object? params = freezed,}) { + return _then(_AgentExtension( +uri: null == uri ? _self.uri : uri // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,required: freezed == required ? _self.required : required // ignore: cast_nullable_to_non_nullable +as bool?,params: freezed == params ? _self._params : params // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/agent_extension.g.dart b/packages/a2a_dart/lib/src/core/agent_extension.g.dart new file mode 100644 index 000000000..af040316b --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_extension.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'agent_extension.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_AgentExtension _$AgentExtensionFromJson(Map json) => + _AgentExtension( + uri: json['uri'] as String, + description: json['description'] as String?, + required: json['required'] as bool?, + params: json['params'] as Map?, + ); + +Map _$AgentExtensionToJson(_AgentExtension instance) => + { + 'uri': instance.uri, + 'description': instance.description, + 'required': instance.required, + 'params': instance.params, + }; diff --git a/packages/a2a_dart/lib/src/core/agent_interface.dart b/packages/a2a_dart/lib/src/core/agent_interface.dart new file mode 100644 index 000000000..0fcdcc141 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_interface.dart @@ -0,0 +1,49 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'agent_card.dart'; +library; + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'agent_interface.freezed.dart'; +part 'agent_interface.g.dart'; + +/// Supported A2A transport protocols. +enum TransportProtocol { + /// JSON-RPC 2.0 over HTTP. + @JsonValue('JSONRPC') + jsonrpc, + + /// gRPC over HTTP/2. + @JsonValue('GRPC') + grpc, + + /// REST-style HTTP with JSON. + @JsonValue('HTTP+JSON') + httpJson, +} + +/// Declares a combination of a target URL and a transport protocol for +/// interacting with an agent. +/// +/// Part of the [AgentCard], this allows an agent to expose the same +/// functionality over multiple transport mechanisms. +@freezed +abstract class AgentInterface with _$AgentInterface { + /// Creates an [AgentInterface]. + const factory AgentInterface({ + /// The URL where this interface is available. + /// + /// In production, this must be a valid absolute HTTPS URL. + required String url, + + /// The transport protocol supported at this URL. + required TransportProtocol transport, + }) = _AgentInterface; + + /// Creates an [AgentInterface] from a JSON object. + factory AgentInterface.fromJson(Map json) => + _$AgentInterfaceFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/agent_interface.freezed.dart b/packages/a2a_dart/lib/src/core/agent_interface.freezed.dart new file mode 100644 index 000000000..867771514 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_interface.freezed.dart @@ -0,0 +1,288 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'agent_interface.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$AgentInterface { + +/// The URL where this interface is available. +/// +/// In production, this must be a valid absolute HTTPS URL. + String get url;/// The transport protocol supported at this URL. + TransportProtocol get transport; +/// Create a copy of AgentInterface +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AgentInterfaceCopyWith get copyWith => _$AgentInterfaceCopyWithImpl(this as AgentInterface, _$identity); + + /// Serializes this AgentInterface to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AgentInterface&&(identical(other.url, url) || other.url == url)&&(identical(other.transport, transport) || other.transport == transport)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,url,transport); + +@override +String toString() { + return 'AgentInterface(url: $url, transport: $transport)'; +} + + +} + +/// @nodoc +abstract mixin class $AgentInterfaceCopyWith<$Res> { + factory $AgentInterfaceCopyWith(AgentInterface value, $Res Function(AgentInterface) _then) = _$AgentInterfaceCopyWithImpl; +@useResult +$Res call({ + String url, TransportProtocol transport +}); + + + + +} +/// @nodoc +class _$AgentInterfaceCopyWithImpl<$Res> + implements $AgentInterfaceCopyWith<$Res> { + _$AgentInterfaceCopyWithImpl(this._self, this._then); + + final AgentInterface _self; + final $Res Function(AgentInterface) _then; + +/// Create a copy of AgentInterface +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? url = null,Object? transport = null,}) { + return _then(_self.copyWith( +url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String,transport: null == transport ? _self.transport : transport // ignore: cast_nullable_to_non_nullable +as TransportProtocol, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AgentInterface]. +extension AgentInterfacePatterns on AgentInterface { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AgentInterface value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AgentInterface() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AgentInterface value) $default,){ +final _that = this; +switch (_that) { +case _AgentInterface(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AgentInterface value)? $default,){ +final _that = this; +switch (_that) { +case _AgentInterface() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String url, TransportProtocol transport)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AgentInterface() when $default != null: +return $default(_that.url,_that.transport);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String url, TransportProtocol transport) $default,) {final _that = this; +switch (_that) { +case _AgentInterface(): +return $default(_that.url,_that.transport);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String url, TransportProtocol transport)? $default,) {final _that = this; +switch (_that) { +case _AgentInterface() when $default != null: +return $default(_that.url,_that.transport);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AgentInterface implements AgentInterface { + const _AgentInterface({required this.url, required this.transport}); + factory _AgentInterface.fromJson(Map json) => _$AgentInterfaceFromJson(json); + +/// The URL where this interface is available. +/// +/// In production, this must be a valid absolute HTTPS URL. +@override final String url; +/// The transport protocol supported at this URL. +@override final TransportProtocol transport; + +/// Create a copy of AgentInterface +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AgentInterfaceCopyWith<_AgentInterface> get copyWith => __$AgentInterfaceCopyWithImpl<_AgentInterface>(this, _$identity); + +@override +Map toJson() { + return _$AgentInterfaceToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AgentInterface&&(identical(other.url, url) || other.url == url)&&(identical(other.transport, transport) || other.transport == transport)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,url,transport); + +@override +String toString() { + return 'AgentInterface(url: $url, transport: $transport)'; +} + + +} + +/// @nodoc +abstract mixin class _$AgentInterfaceCopyWith<$Res> implements $AgentInterfaceCopyWith<$Res> { + factory _$AgentInterfaceCopyWith(_AgentInterface value, $Res Function(_AgentInterface) _then) = __$AgentInterfaceCopyWithImpl; +@override @useResult +$Res call({ + String url, TransportProtocol transport +}); + + + + +} +/// @nodoc +class __$AgentInterfaceCopyWithImpl<$Res> + implements _$AgentInterfaceCopyWith<$Res> { + __$AgentInterfaceCopyWithImpl(this._self, this._then); + + final _AgentInterface _self; + final $Res Function(_AgentInterface) _then; + +/// Create a copy of AgentInterface +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? url = null,Object? transport = null,}) { + return _then(_AgentInterface( +url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String,transport: null == transport ? _self.transport : transport // ignore: cast_nullable_to_non_nullable +as TransportProtocol, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/agent_interface.g.dart b/packages/a2a_dart/lib/src/core/agent_interface.g.dart new file mode 100644 index 000000000..89c283861 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_interface.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'agent_interface.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_AgentInterface _$AgentInterfaceFromJson(Map json) => + _AgentInterface( + url: json['url'] as String, + transport: $enumDecode(_$TransportProtocolEnumMap, json['transport']), + ); + +Map _$AgentInterfaceToJson(_AgentInterface instance) => + { + 'url': instance.url, + 'transport': _$TransportProtocolEnumMap[instance.transport]!, + }; + +const _$TransportProtocolEnumMap = { + TransportProtocol.jsonrpc: 'JSONRPC', + TransportProtocol.grpc: 'GRPC', + TransportProtocol.httpJson: 'HTTP+JSON', +}; diff --git a/packages/a2a_dart/lib/src/core/agent_provider.dart b/packages/a2a_dart/lib/src/core/agent_provider.dart new file mode 100644 index 000000000..b8443adee --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_provider.dart @@ -0,0 +1,31 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'agent_card.dart'; +library; + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'agent_provider.freezed.dart'; +part 'agent_provider.g.dart'; + +/// Information about the agent's service provider. +/// +/// Part of the [AgentCard], this provides information about the entity that +/// created and maintains the agent. +@freezed +abstract class AgentProvider with _$AgentProvider { + /// Creates an [AgentProvider]. + const factory AgentProvider({ + /// The name of the agent provider's organization. + required String organization, + + /// A URL for the agent provider's website or relevant documentation. + required String url, + }) = _AgentProvider; + + /// Creates an [AgentProvider] from a JSON object. + factory AgentProvider.fromJson(Map json) => + _$AgentProviderFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/agent_provider.freezed.dart b/packages/a2a_dart/lib/src/core/agent_provider.freezed.dart new file mode 100644 index 000000000..6cf6207ec --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_provider.freezed.dart @@ -0,0 +1,284 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'agent_provider.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$AgentProvider { + +/// The name of the agent provider's organization. + String get organization;/// A URL for the agent provider's website or relevant documentation. + String get url; +/// Create a copy of AgentProvider +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AgentProviderCopyWith get copyWith => _$AgentProviderCopyWithImpl(this as AgentProvider, _$identity); + + /// Serializes this AgentProvider to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AgentProvider&&(identical(other.organization, organization) || other.organization == organization)&&(identical(other.url, url) || other.url == url)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,organization,url); + +@override +String toString() { + return 'AgentProvider(organization: $organization, url: $url)'; +} + + +} + +/// @nodoc +abstract mixin class $AgentProviderCopyWith<$Res> { + factory $AgentProviderCopyWith(AgentProvider value, $Res Function(AgentProvider) _then) = _$AgentProviderCopyWithImpl; +@useResult +$Res call({ + String organization, String url +}); + + + + +} +/// @nodoc +class _$AgentProviderCopyWithImpl<$Res> + implements $AgentProviderCopyWith<$Res> { + _$AgentProviderCopyWithImpl(this._self, this._then); + + final AgentProvider _self; + final $Res Function(AgentProvider) _then; + +/// Create a copy of AgentProvider +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? organization = null,Object? url = null,}) { + return _then(_self.copyWith( +organization: null == organization ? _self.organization : organization // ignore: cast_nullable_to_non_nullable +as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AgentProvider]. +extension AgentProviderPatterns on AgentProvider { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AgentProvider value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AgentProvider() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AgentProvider value) $default,){ +final _that = this; +switch (_that) { +case _AgentProvider(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AgentProvider value)? $default,){ +final _that = this; +switch (_that) { +case _AgentProvider() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String organization, String url)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AgentProvider() when $default != null: +return $default(_that.organization,_that.url);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String organization, String url) $default,) {final _that = this; +switch (_that) { +case _AgentProvider(): +return $default(_that.organization,_that.url);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String organization, String url)? $default,) {final _that = this; +switch (_that) { +case _AgentProvider() when $default != null: +return $default(_that.organization,_that.url);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AgentProvider implements AgentProvider { + const _AgentProvider({required this.organization, required this.url}); + factory _AgentProvider.fromJson(Map json) => _$AgentProviderFromJson(json); + +/// The name of the agent provider's organization. +@override final String organization; +/// A URL for the agent provider's website or relevant documentation. +@override final String url; + +/// Create a copy of AgentProvider +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AgentProviderCopyWith<_AgentProvider> get copyWith => __$AgentProviderCopyWithImpl<_AgentProvider>(this, _$identity); + +@override +Map toJson() { + return _$AgentProviderToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AgentProvider&&(identical(other.organization, organization) || other.organization == organization)&&(identical(other.url, url) || other.url == url)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,organization,url); + +@override +String toString() { + return 'AgentProvider(organization: $organization, url: $url)'; +} + + +} + +/// @nodoc +abstract mixin class _$AgentProviderCopyWith<$Res> implements $AgentProviderCopyWith<$Res> { + factory _$AgentProviderCopyWith(_AgentProvider value, $Res Function(_AgentProvider) _then) = __$AgentProviderCopyWithImpl; +@override @useResult +$Res call({ + String organization, String url +}); + + + + +} +/// @nodoc +class __$AgentProviderCopyWithImpl<$Res> + implements _$AgentProviderCopyWith<$Res> { + __$AgentProviderCopyWithImpl(this._self, this._then); + + final _AgentProvider _self; + final $Res Function(_AgentProvider) _then; + +/// Create a copy of AgentProvider +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? organization = null,Object? url = null,}) { + return _then(_AgentProvider( +organization: null == organization ? _self.organization : organization // ignore: cast_nullable_to_non_nullable +as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/agent_provider.g.dart b/packages/a2a_dart/lib/src/core/agent_provider.g.dart new file mode 100644 index 000000000..82ce73596 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_provider.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'agent_provider.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_AgentProvider _$AgentProviderFromJson(Map json) => + _AgentProvider( + organization: json['organization'] as String, + url: json['url'] as String, + ); + +Map _$AgentProviderToJson(_AgentProvider instance) => + { + 'organization': instance.organization, + 'url': instance.url, + }; diff --git a/packages/a2a_dart/lib/src/core/agent_skill.dart b/packages/a2a_dart/lib/src/core/agent_skill.dart new file mode 100644 index 000000000..c71079982 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_skill.dart @@ -0,0 +1,53 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'agent_card.dart'; +library; + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'agent_skill.freezed.dart'; +part 'agent_skill.g.dart'; + +/// Represents a distinct capability or function that an agent can perform. +/// +/// Part of the [AgentCard], this class allows an agent to advertise its +/// specific skills, making them discoverable to clients. +@freezed +abstract class AgentSkill with _$AgentSkill { + /// Creates an [AgentSkill]. + const factory AgentSkill({ + /// A unique identifier for the agent's skill (e.g., "weather-forecast"). + required String id, + + /// A human-readable name for the skill (e.g., "Weather Forecast"). + required String name, + + /// A detailed description of the skill, intended to help clients or users + /// understand its purpose and functionality. + required String description, + + /// A set of keywords describing the skill's capabilities. + required List tags, + + /// Example prompts or scenarios that this skill can handle, providing a + /// hint to the client on how to use the skill. + List? examples, + + /// The set of supported input MIME types for this skill, overriding the + /// agent's defaults. + List? inputModes, + + /// The set of supported output MIME types for this skill, overriding the + /// agent's defaults. + List? outputModes, + + /// Security schemes necessary for the agent to leverage this skill. + List>>? security, + }) = _AgentSkill; + + /// Creates an [AgentSkill] from a JSON object. + factory AgentSkill.fromJson(Map json) => + _$AgentSkillFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/agent_skill.freezed.dart b/packages/a2a_dart/lib/src/core/agent_skill.freezed.dart new file mode 100644 index 000000000..37062f7cd --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_skill.freezed.dart @@ -0,0 +1,368 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'agent_skill.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$AgentSkill { + +/// A unique identifier for the agent's skill (e.g., "weather-forecast"). + String get id;/// A human-readable name for the skill (e.g., "Weather Forecast"). + String get name;/// A detailed description of the skill, intended to help clients or users +/// understand its purpose and functionality. + String get description;/// A set of keywords describing the skill's capabilities. + List get tags;/// Example prompts or scenarios that this skill can handle, providing a +/// hint to the client on how to use the skill. + List? get examples;/// The set of supported input MIME types for this skill, overriding the +/// agent's defaults. + List? get inputModes;/// The set of supported output MIME types for this skill, overriding the +/// agent's defaults. + List? get outputModes;/// Security schemes necessary for the agent to leverage this skill. + List>>? get security; +/// Create a copy of AgentSkill +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$AgentSkillCopyWith get copyWith => _$AgentSkillCopyWithImpl(this as AgentSkill, _$identity); + + /// Serializes this AgentSkill to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is AgentSkill&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.examples, examples)&&const DeepCollectionEquality().equals(other.inputModes, inputModes)&&const DeepCollectionEquality().equals(other.outputModes, outputModes)&&const DeepCollectionEquality().equals(other.security, security)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(examples),const DeepCollectionEquality().hash(inputModes),const DeepCollectionEquality().hash(outputModes),const DeepCollectionEquality().hash(security)); + +@override +String toString() { + return 'AgentSkill(id: $id, name: $name, description: $description, tags: $tags, examples: $examples, inputModes: $inputModes, outputModes: $outputModes, security: $security)'; +} + + +} + +/// @nodoc +abstract mixin class $AgentSkillCopyWith<$Res> { + factory $AgentSkillCopyWith(AgentSkill value, $Res Function(AgentSkill) _then) = _$AgentSkillCopyWithImpl; +@useResult +$Res call({ + String id, String name, String description, List tags, List? examples, List? inputModes, List? outputModes, List>>? security +}); + + + + +} +/// @nodoc +class _$AgentSkillCopyWithImpl<$Res> + implements $AgentSkillCopyWith<$Res> { + _$AgentSkillCopyWithImpl(this._self, this._then); + + final AgentSkill _self; + final $Res Function(AgentSkill) _then; + +/// Create a copy of AgentSkill +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? description = null,Object? tags = null,Object? examples = freezed,Object? inputModes = freezed,Object? outputModes = freezed,Object? security = freezed,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable +as List,examples: freezed == examples ? _self.examples : examples // ignore: cast_nullable_to_non_nullable +as List?,inputModes: freezed == inputModes ? _self.inputModes : inputModes // ignore: cast_nullable_to_non_nullable +as List?,outputModes: freezed == outputModes ? _self.outputModes : outputModes // ignore: cast_nullable_to_non_nullable +as List?,security: freezed == security ? _self.security : security // ignore: cast_nullable_to_non_nullable +as List>>?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [AgentSkill]. +extension AgentSkillPatterns on AgentSkill { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _AgentSkill value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _AgentSkill() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _AgentSkill value) $default,){ +final _that = this; +switch (_that) { +case _AgentSkill(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _AgentSkill value)? $default,){ +final _that = this; +switch (_that) { +case _AgentSkill() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String name, String description, List tags, List? examples, List? inputModes, List? outputModes, List>>? security)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _AgentSkill() when $default != null: +return $default(_that.id,_that.name,_that.description,_that.tags,_that.examples,_that.inputModes,_that.outputModes,_that.security);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String name, String description, List tags, List? examples, List? inputModes, List? outputModes, List>>? security) $default,) {final _that = this; +switch (_that) { +case _AgentSkill(): +return $default(_that.id,_that.name,_that.description,_that.tags,_that.examples,_that.inputModes,_that.outputModes,_that.security);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String name, String description, List tags, List? examples, List? inputModes, List? outputModes, List>>? security)? $default,) {final _that = this; +switch (_that) { +case _AgentSkill() when $default != null: +return $default(_that.id,_that.name,_that.description,_that.tags,_that.examples,_that.inputModes,_that.outputModes,_that.security);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _AgentSkill implements AgentSkill { + const _AgentSkill({required this.id, required this.name, required this.description, required final List tags, final List? examples, final List? inputModes, final List? outputModes, final List>>? security}): _tags = tags,_examples = examples,_inputModes = inputModes,_outputModes = outputModes,_security = security; + factory _AgentSkill.fromJson(Map json) => _$AgentSkillFromJson(json); + +/// A unique identifier for the agent's skill (e.g., "weather-forecast"). +@override final String id; +/// A human-readable name for the skill (e.g., "Weather Forecast"). +@override final String name; +/// A detailed description of the skill, intended to help clients or users +/// understand its purpose and functionality. +@override final String description; +/// A set of keywords describing the skill's capabilities. + final List _tags; +/// A set of keywords describing the skill's capabilities. +@override List get tags { + if (_tags is EqualUnmodifiableListView) return _tags; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_tags); +} + +/// Example prompts or scenarios that this skill can handle, providing a +/// hint to the client on how to use the skill. + final List? _examples; +/// Example prompts or scenarios that this skill can handle, providing a +/// hint to the client on how to use the skill. +@override List? get examples { + final value = _examples; + if (value == null) return null; + if (_examples is EqualUnmodifiableListView) return _examples; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// The set of supported input MIME types for this skill, overriding the +/// agent's defaults. + final List? _inputModes; +/// The set of supported input MIME types for this skill, overriding the +/// agent's defaults. +@override List? get inputModes { + final value = _inputModes; + if (value == null) return null; + if (_inputModes is EqualUnmodifiableListView) return _inputModes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// The set of supported output MIME types for this skill, overriding the +/// agent's defaults. + final List? _outputModes; +/// The set of supported output MIME types for this skill, overriding the +/// agent's defaults. +@override List? get outputModes { + final value = _outputModes; + if (value == null) return null; + if (_outputModes is EqualUnmodifiableListView) return _outputModes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// Security schemes necessary for the agent to leverage this skill. + final List>>? _security; +/// Security schemes necessary for the agent to leverage this skill. +@override List>>? get security { + final value = _security; + if (value == null) return null; + if (_security is EqualUnmodifiableListView) return _security; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + + +/// Create a copy of AgentSkill +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$AgentSkillCopyWith<_AgentSkill> get copyWith => __$AgentSkillCopyWithImpl<_AgentSkill>(this, _$identity); + +@override +Map toJson() { + return _$AgentSkillToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _AgentSkill&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._examples, _examples)&&const DeepCollectionEquality().equals(other._inputModes, _inputModes)&&const DeepCollectionEquality().equals(other._outputModes, _outputModes)&&const DeepCollectionEquality().equals(other._security, _security)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_examples),const DeepCollectionEquality().hash(_inputModes),const DeepCollectionEquality().hash(_outputModes),const DeepCollectionEquality().hash(_security)); + +@override +String toString() { + return 'AgentSkill(id: $id, name: $name, description: $description, tags: $tags, examples: $examples, inputModes: $inputModes, outputModes: $outputModes, security: $security)'; +} + + +} + +/// @nodoc +abstract mixin class _$AgentSkillCopyWith<$Res> implements $AgentSkillCopyWith<$Res> { + factory _$AgentSkillCopyWith(_AgentSkill value, $Res Function(_AgentSkill) _then) = __$AgentSkillCopyWithImpl; +@override @useResult +$Res call({ + String id, String name, String description, List tags, List? examples, List? inputModes, List? outputModes, List>>? security +}); + + + + +} +/// @nodoc +class __$AgentSkillCopyWithImpl<$Res> + implements _$AgentSkillCopyWith<$Res> { + __$AgentSkillCopyWithImpl(this._self, this._then); + + final _AgentSkill _self; + final $Res Function(_AgentSkill) _then; + +/// Create a copy of AgentSkill +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? description = null,Object? tags = null,Object? examples = freezed,Object? inputModes = freezed,Object? outputModes = freezed,Object? security = freezed,}) { + return _then(_AgentSkill( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable +as List,examples: freezed == examples ? _self._examples : examples // ignore: cast_nullable_to_non_nullable +as List?,inputModes: freezed == inputModes ? _self._inputModes : inputModes // ignore: cast_nullable_to_non_nullable +as List?,outputModes: freezed == outputModes ? _self._outputModes : outputModes // ignore: cast_nullable_to_non_nullable +as List?,security: freezed == security ? _self._security : security // ignore: cast_nullable_to_non_nullable +as List>>?, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/agent_skill.g.dart b/packages/a2a_dart/lib/src/core/agent_skill.g.dart new file mode 100644 index 000000000..4a4676f43 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/agent_skill.g.dart @@ -0,0 +1,45 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'agent_skill.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_AgentSkill _$AgentSkillFromJson(Map json) => _AgentSkill( + id: json['id'] as String, + name: json['name'] as String, + description: json['description'] as String, + tags: (json['tags'] as List).map((e) => e as String).toList(), + examples: (json['examples'] as List?) + ?.map((e) => e as String) + .toList(), + inputModes: (json['inputModes'] as List?) + ?.map((e) => e as String) + .toList(), + outputModes: (json['outputModes'] as List?) + ?.map((e) => e as String) + .toList(), + security: (json['security'] as List?) + ?.map( + (e) => (e as Map).map( + (k, e) => MapEntry( + k, + (e as List).map((e) => e as String).toList(), + ), + ), + ) + .toList(), +); + +Map _$AgentSkillToJson(_AgentSkill instance) => + { + 'id': instance.id, + 'name': instance.name, + 'description': instance.description, + 'tags': instance.tags, + 'examples': instance.examples, + 'inputModes': instance.inputModes, + 'outputModes': instance.outputModes, + 'security': instance.security, + }; diff --git a/packages/a2a_dart/lib/src/core/events.dart b/packages/a2a_dart/lib/src/core/events.dart new file mode 100644 index 000000000..46c4cd26a --- /dev/null +++ b/packages/a2a_dart/lib/src/core/events.dart @@ -0,0 +1,111 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'task.dart'; + +part 'events.freezed.dart'; +part 'events.g.dart'; + +/// Represents an event sent from the server during a streaming task. +/// +/// This is a legacy name, [Event] should be used instead. +@Freezed(unionKey: 'kind', unionValueCase: FreezedUnionCase.snake) +abstract class StreamingEvent with _$StreamingEvent { + /// Indicates an update to the task's status. + const factory StreamingEvent.taskStatusUpdate({ + /// The type of this event, always 'task_status_update'. + @Default('task_status_update') String kind, + + /// The unique ID of the updated task. + required String taskId, + + /// The unique context ID for the task. + required String contextId, + + /// The new status of the task. + required TaskStatus status, + + /// If `true`, this is the final event for this task stream. + required bool final_, + }) = TaskStatusUpdateEvent; + + /// Indicates a new or updated artifact related to the task. + const factory StreamingEvent.taskArtifactUpdate({ + /// The type of this event, always 'task_artifact_update'. + @Default('task_artifact_update') String kind, + + /// The unique ID of the task this artifact belongs to. + required String taskId, + + /// The unique context ID for the task. + required String contextId, + + /// The artifact data. + required Artifact artifact, + + /// If `true`, this artifact's content should be appended to any previous + /// content for the same `artifact.artifactId`. + required bool append, + + /// If `true`, this is the last chunk of data for this artifact. + required bool lastChunk, + }) = TaskArtifactUpdateEvent; + + /// Deserializes a [StreamingEvent] from a JSON object. + factory StreamingEvent.fromJson(Map json) => + _$StreamingEventFromJson(json); +} + +/// Represents an event received from the server, typically during a stream. +/// +/// This is a discriminated union based on the `kind` field. It's used by the +/// client to handle various types of updates from the server in a type-safe +/// way. +@Freezed(unionKey: 'kind', unionValueCase: FreezedUnionCase.snake) +sealed class Event with _$Event { + /// Indicates an update to the task's status. + const factory Event.taskStatusUpdate({ + /// The type of this event, always 'task_status_update'. + @Default('task_status_update') String kind, + + /// The unique ID of the updated task. + required String taskId, + + /// The unique context ID for the task. + required String contextId, + + /// The new status of the task. + required TaskStatus status, + + /// If `true`, this is the final event for this task stream. + required bool final_, + }) = TaskStatusUpdate; + + /// Indicates a new or updated artifact related to the task. + const factory Event.taskArtifactUpdate({ + /// The type of this event, always 'task_artifact_update'. + @Default('task_artifact_update') String kind, + + /// The unique ID of the task this artifact belongs to. + required String taskId, + + /// The unique context ID for the task. + required String contextId, + + /// The artifact data. + required Artifact artifact, + + /// If `true`, this artifact's content should be appended to any previous + /// content for the same `artifact.artifactId`. + required bool append, + + /// If `true`, this is the last chunk of data for this artifact. + required bool lastChunk, + }) = TaskArtifactUpdate; + + /// Deserializes an [Event] from a JSON object. + factory Event.fromJson(Map json) => _$EventFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/events.freezed.dart b/packages/a2a_dart/lib/src/core/events.freezed.dart new file mode 100644 index 000000000..53360631c --- /dev/null +++ b/packages/a2a_dart/lib/src/core/events.freezed.dart @@ -0,0 +1,836 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'events.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +StreamingEvent _$StreamingEventFromJson( + Map json +) { + switch (json['kind']) { + case 'task_status_update': + return TaskStatusUpdateEvent.fromJson( + json + ); + case 'task_artifact_update': + return TaskArtifactUpdateEvent.fromJson( + json + ); + + default: + throw CheckedFromJsonException( + json, + 'kind', + 'StreamingEvent', + 'Invalid union type "${json['kind']}"!' +); + } + +} + +/// @nodoc +mixin _$StreamingEvent { + +/// The type of this event, always 'task_status_update'. + String get kind;/// The unique ID of the updated task. + String get taskId;/// The unique context ID for the task. + String get contextId; +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$StreamingEventCopyWith get copyWith => _$StreamingEventCopyWithImpl(this as StreamingEvent, _$identity); + + /// Serializes this StreamingEvent to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is StreamingEvent&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,taskId,contextId); + +@override +String toString() { + return 'StreamingEvent(kind: $kind, taskId: $taskId, contextId: $contextId)'; +} + + +} + +/// @nodoc +abstract mixin class $StreamingEventCopyWith<$Res> { + factory $StreamingEventCopyWith(StreamingEvent value, $Res Function(StreamingEvent) _then) = _$StreamingEventCopyWithImpl; +@useResult +$Res call({ + String kind, String taskId, String contextId +}); + + + + +} +/// @nodoc +class _$StreamingEventCopyWithImpl<$Res> + implements $StreamingEventCopyWith<$Res> { + _$StreamingEventCopyWithImpl(this._self, this._then); + + final StreamingEvent _self; + final $Res Function(StreamingEvent) _then; + +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? kind = null,Object? taskId = null,Object? contextId = null,}) { + return _then(_self.copyWith( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [StreamingEvent]. +extension StreamingEventPatterns on StreamingEvent { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( TaskStatusUpdateEvent value)? taskStatusUpdate,TResult Function( TaskArtifactUpdateEvent value)? taskArtifactUpdate,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case TaskStatusUpdateEvent() when taskStatusUpdate != null: +return taskStatusUpdate(_that);case TaskArtifactUpdateEvent() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( TaskStatusUpdateEvent value) taskStatusUpdate,required TResult Function( TaskArtifactUpdateEvent value) taskArtifactUpdate,}){ +final _that = this; +switch (_that) { +case TaskStatusUpdateEvent(): +return taskStatusUpdate(_that);case TaskArtifactUpdateEvent(): +return taskArtifactUpdate(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( TaskStatusUpdateEvent value)? taskStatusUpdate,TResult? Function( TaskArtifactUpdateEvent value)? taskArtifactUpdate,}){ +final _that = this; +switch (_that) { +case TaskStatusUpdateEvent() when taskStatusUpdate != null: +return taskStatusUpdate(_that);case TaskArtifactUpdateEvent() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( String kind, String taskId, String contextId, TaskStatus status, bool final_)? taskStatusUpdate,TResult Function( String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk)? taskArtifactUpdate,required TResult orElse(),}) {final _that = this; +switch (_that) { +case TaskStatusUpdateEvent() when taskStatusUpdate != null: +return taskStatusUpdate(_that.kind,_that.taskId,_that.contextId,_that.status,_that.final_);case TaskArtifactUpdateEvent() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that.kind,_that.taskId,_that.contextId,_that.artifact,_that.append,_that.lastChunk);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( String kind, String taskId, String contextId, TaskStatus status, bool final_) taskStatusUpdate,required TResult Function( String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk) taskArtifactUpdate,}) {final _that = this; +switch (_that) { +case TaskStatusUpdateEvent(): +return taskStatusUpdate(_that.kind,_that.taskId,_that.contextId,_that.status,_that.final_);case TaskArtifactUpdateEvent(): +return taskArtifactUpdate(_that.kind,_that.taskId,_that.contextId,_that.artifact,_that.append,_that.lastChunk);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( String kind, String taskId, String contextId, TaskStatus status, bool final_)? taskStatusUpdate,TResult? Function( String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk)? taskArtifactUpdate,}) {final _that = this; +switch (_that) { +case TaskStatusUpdateEvent() when taskStatusUpdate != null: +return taskStatusUpdate(_that.kind,_that.taskId,_that.contextId,_that.status,_that.final_);case TaskArtifactUpdateEvent() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that.kind,_that.taskId,_that.contextId,_that.artifact,_that.append,_that.lastChunk);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class TaskStatusUpdateEvent implements StreamingEvent { + const TaskStatusUpdateEvent({this.kind = 'task_status_update', required this.taskId, required this.contextId, required this.status, required this.final_}); + factory TaskStatusUpdateEvent.fromJson(Map json) => _$TaskStatusUpdateEventFromJson(json); + +/// The type of this event, always 'task_status_update'. +@override@JsonKey() final String kind; +/// The unique ID of the updated task. +@override final String taskId; +/// The unique context ID for the task. +@override final String contextId; +/// The new status of the task. + final TaskStatus status; +/// If `true`, this is the final event for this task stream. + final bool final_; + +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TaskStatusUpdateEventCopyWith get copyWith => _$TaskStatusUpdateEventCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$TaskStatusUpdateEventToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TaskStatusUpdateEvent&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.status, status) || other.status == status)&&(identical(other.final_, final_) || other.final_ == final_)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,taskId,contextId,status,final_); + +@override +String toString() { + return 'StreamingEvent.taskStatusUpdate(kind: $kind, taskId: $taskId, contextId: $contextId, status: $status, final_: $final_)'; +} + + +} + +/// @nodoc +abstract mixin class $TaskStatusUpdateEventCopyWith<$Res> implements $StreamingEventCopyWith<$Res> { + factory $TaskStatusUpdateEventCopyWith(TaskStatusUpdateEvent value, $Res Function(TaskStatusUpdateEvent) _then) = _$TaskStatusUpdateEventCopyWithImpl; +@override @useResult +$Res call({ + String kind, String taskId, String contextId, TaskStatus status, bool final_ +}); + + +$TaskStatusCopyWith<$Res> get status; + +} +/// @nodoc +class _$TaskStatusUpdateEventCopyWithImpl<$Res> + implements $TaskStatusUpdateEventCopyWith<$Res> { + _$TaskStatusUpdateEventCopyWithImpl(this._self, this._then); + + final TaskStatusUpdateEvent _self; + final $Res Function(TaskStatusUpdateEvent) _then; + +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? kind = null,Object? taskId = null,Object? contextId = null,Object? status = null,Object? final_ = null,}) { + return _then(TaskStatusUpdateEvent( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as TaskStatus,final_: null == final_ ? _self.final_ : final_ // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$TaskStatusCopyWith<$Res> get status { + + return $TaskStatusCopyWith<$Res>(_self.status, (value) { + return _then(_self.copyWith(status: value)); + }); +} +} + +/// @nodoc +@JsonSerializable() + +class TaskArtifactUpdateEvent implements StreamingEvent { + const TaskArtifactUpdateEvent({this.kind = 'task_artifact_update', required this.taskId, required this.contextId, required this.artifact, required this.append, required this.lastChunk}); + factory TaskArtifactUpdateEvent.fromJson(Map json) => _$TaskArtifactUpdateEventFromJson(json); + +/// The type of this event, always 'task_artifact_update'. +@override@JsonKey() final String kind; +/// The unique ID of the task this artifact belongs to. +@override final String taskId; +/// The unique context ID for the task. +@override final String contextId; +/// The artifact data. + final Artifact artifact; +/// If `true`, this artifact's content should be appended to any previous +/// content for the same `artifact.artifactId`. + final bool append; +/// If `true`, this is the last chunk of data for this artifact. + final bool lastChunk; + +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TaskArtifactUpdateEventCopyWith get copyWith => _$TaskArtifactUpdateEventCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$TaskArtifactUpdateEventToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TaskArtifactUpdateEvent&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.artifact, artifact) || other.artifact == artifact)&&(identical(other.append, append) || other.append == append)&&(identical(other.lastChunk, lastChunk) || other.lastChunk == lastChunk)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,taskId,contextId,artifact,append,lastChunk); + +@override +String toString() { + return 'StreamingEvent.taskArtifactUpdate(kind: $kind, taskId: $taskId, contextId: $contextId, artifact: $artifact, append: $append, lastChunk: $lastChunk)'; +} + + +} + +/// @nodoc +abstract mixin class $TaskArtifactUpdateEventCopyWith<$Res> implements $StreamingEventCopyWith<$Res> { + factory $TaskArtifactUpdateEventCopyWith(TaskArtifactUpdateEvent value, $Res Function(TaskArtifactUpdateEvent) _then) = _$TaskArtifactUpdateEventCopyWithImpl; +@override @useResult +$Res call({ + String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk +}); + + +$ArtifactCopyWith<$Res> get artifact; + +} +/// @nodoc +class _$TaskArtifactUpdateEventCopyWithImpl<$Res> + implements $TaskArtifactUpdateEventCopyWith<$Res> { + _$TaskArtifactUpdateEventCopyWithImpl(this._self, this._then); + + final TaskArtifactUpdateEvent _self; + final $Res Function(TaskArtifactUpdateEvent) _then; + +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? kind = null,Object? taskId = null,Object? contextId = null,Object? artifact = null,Object? append = null,Object? lastChunk = null,}) { + return _then(TaskArtifactUpdateEvent( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String,artifact: null == artifact ? _self.artifact : artifact // ignore: cast_nullable_to_non_nullable +as Artifact,append: null == append ? _self.append : append // ignore: cast_nullable_to_non_nullable +as bool,lastChunk: null == lastChunk ? _self.lastChunk : lastChunk // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + +/// Create a copy of StreamingEvent +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$ArtifactCopyWith<$Res> get artifact { + + return $ArtifactCopyWith<$Res>(_self.artifact, (value) { + return _then(_self.copyWith(artifact: value)); + }); +} +} + +Event _$EventFromJson( + Map json +) { + switch (json['kind']) { + case 'task_status_update': + return TaskStatusUpdate.fromJson( + json + ); + case 'task_artifact_update': + return TaskArtifactUpdate.fromJson( + json + ); + + default: + throw CheckedFromJsonException( + json, + 'kind', + 'Event', + 'Invalid union type "${json['kind']}"!' +); + } + +} + +/// @nodoc +mixin _$Event { + +/// The type of this event, always 'task_status_update'. + String get kind;/// The unique ID of the updated task. + String get taskId;/// The unique context ID for the task. + String get contextId; +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$EventCopyWith get copyWith => _$EventCopyWithImpl(this as Event, _$identity); + + /// Serializes this Event to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Event&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,taskId,contextId); + +@override +String toString() { + return 'Event(kind: $kind, taskId: $taskId, contextId: $contextId)'; +} + + +} + +/// @nodoc +abstract mixin class $EventCopyWith<$Res> { + factory $EventCopyWith(Event value, $Res Function(Event) _then) = _$EventCopyWithImpl; +@useResult +$Res call({ + String kind, String taskId, String contextId +}); + + + + +} +/// @nodoc +class _$EventCopyWithImpl<$Res> + implements $EventCopyWith<$Res> { + _$EventCopyWithImpl(this._self, this._then); + + final Event _self; + final $Res Function(Event) _then; + +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? kind = null,Object? taskId = null,Object? contextId = null,}) { + return _then(_self.copyWith( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [Event]. +extension EventPatterns on Event { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( TaskStatusUpdate value)? taskStatusUpdate,TResult Function( TaskArtifactUpdate value)? taskArtifactUpdate,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case TaskStatusUpdate() when taskStatusUpdate != null: +return taskStatusUpdate(_that);case TaskArtifactUpdate() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( TaskStatusUpdate value) taskStatusUpdate,required TResult Function( TaskArtifactUpdate value) taskArtifactUpdate,}){ +final _that = this; +switch (_that) { +case TaskStatusUpdate(): +return taskStatusUpdate(_that);case TaskArtifactUpdate(): +return taskArtifactUpdate(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( TaskStatusUpdate value)? taskStatusUpdate,TResult? Function( TaskArtifactUpdate value)? taskArtifactUpdate,}){ +final _that = this; +switch (_that) { +case TaskStatusUpdate() when taskStatusUpdate != null: +return taskStatusUpdate(_that);case TaskArtifactUpdate() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( String kind, String taskId, String contextId, TaskStatus status, bool final_)? taskStatusUpdate,TResult Function( String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk)? taskArtifactUpdate,required TResult orElse(),}) {final _that = this; +switch (_that) { +case TaskStatusUpdate() when taskStatusUpdate != null: +return taskStatusUpdate(_that.kind,_that.taskId,_that.contextId,_that.status,_that.final_);case TaskArtifactUpdate() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that.kind,_that.taskId,_that.contextId,_that.artifact,_that.append,_that.lastChunk);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( String kind, String taskId, String contextId, TaskStatus status, bool final_) taskStatusUpdate,required TResult Function( String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk) taskArtifactUpdate,}) {final _that = this; +switch (_that) { +case TaskStatusUpdate(): +return taskStatusUpdate(_that.kind,_that.taskId,_that.contextId,_that.status,_that.final_);case TaskArtifactUpdate(): +return taskArtifactUpdate(_that.kind,_that.taskId,_that.contextId,_that.artifact,_that.append,_that.lastChunk);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( String kind, String taskId, String contextId, TaskStatus status, bool final_)? taskStatusUpdate,TResult? Function( String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk)? taskArtifactUpdate,}) {final _that = this; +switch (_that) { +case TaskStatusUpdate() when taskStatusUpdate != null: +return taskStatusUpdate(_that.kind,_that.taskId,_that.contextId,_that.status,_that.final_);case TaskArtifactUpdate() when taskArtifactUpdate != null: +return taskArtifactUpdate(_that.kind,_that.taskId,_that.contextId,_that.artifact,_that.append,_that.lastChunk);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class TaskStatusUpdate implements Event { + const TaskStatusUpdate({this.kind = 'task_status_update', required this.taskId, required this.contextId, required this.status, required this.final_}); + factory TaskStatusUpdate.fromJson(Map json) => _$TaskStatusUpdateFromJson(json); + +/// The type of this event, always 'task_status_update'. +@override@JsonKey() final String kind; +/// The unique ID of the updated task. +@override final String taskId; +/// The unique context ID for the task. +@override final String contextId; +/// The new status of the task. + final TaskStatus status; +/// If `true`, this is the final event for this task stream. + final bool final_; + +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TaskStatusUpdateCopyWith get copyWith => _$TaskStatusUpdateCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$TaskStatusUpdateToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TaskStatusUpdate&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.status, status) || other.status == status)&&(identical(other.final_, final_) || other.final_ == final_)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,taskId,contextId,status,final_); + +@override +String toString() { + return 'Event.taskStatusUpdate(kind: $kind, taskId: $taskId, contextId: $contextId, status: $status, final_: $final_)'; +} + + +} + +/// @nodoc +abstract mixin class $TaskStatusUpdateCopyWith<$Res> implements $EventCopyWith<$Res> { + factory $TaskStatusUpdateCopyWith(TaskStatusUpdate value, $Res Function(TaskStatusUpdate) _then) = _$TaskStatusUpdateCopyWithImpl; +@override @useResult +$Res call({ + String kind, String taskId, String contextId, TaskStatus status, bool final_ +}); + + +$TaskStatusCopyWith<$Res> get status; + +} +/// @nodoc +class _$TaskStatusUpdateCopyWithImpl<$Res> + implements $TaskStatusUpdateCopyWith<$Res> { + _$TaskStatusUpdateCopyWithImpl(this._self, this._then); + + final TaskStatusUpdate _self; + final $Res Function(TaskStatusUpdate) _then; + +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? kind = null,Object? taskId = null,Object? contextId = null,Object? status = null,Object? final_ = null,}) { + return _then(TaskStatusUpdate( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as TaskStatus,final_: null == final_ ? _self.final_ : final_ // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$TaskStatusCopyWith<$Res> get status { + + return $TaskStatusCopyWith<$Res>(_self.status, (value) { + return _then(_self.copyWith(status: value)); + }); +} +} + +/// @nodoc +@JsonSerializable() + +class TaskArtifactUpdate implements Event { + const TaskArtifactUpdate({this.kind = 'task_artifact_update', required this.taskId, required this.contextId, required this.artifact, required this.append, required this.lastChunk}); + factory TaskArtifactUpdate.fromJson(Map json) => _$TaskArtifactUpdateFromJson(json); + +/// The type of this event, always 'task_artifact_update'. +@override@JsonKey() final String kind; +/// The unique ID of the task this artifact belongs to. +@override final String taskId; +/// The unique context ID for the task. +@override final String contextId; +/// The artifact data. + final Artifact artifact; +/// If `true`, this artifact's content should be appended to any previous +/// content for the same `artifact.artifactId`. + final bool append; +/// If `true`, this is the last chunk of data for this artifact. + final bool lastChunk; + +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TaskArtifactUpdateCopyWith get copyWith => _$TaskArtifactUpdateCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$TaskArtifactUpdateToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TaskArtifactUpdate&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.artifact, artifact) || other.artifact == artifact)&&(identical(other.append, append) || other.append == append)&&(identical(other.lastChunk, lastChunk) || other.lastChunk == lastChunk)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,taskId,contextId,artifact,append,lastChunk); + +@override +String toString() { + return 'Event.taskArtifactUpdate(kind: $kind, taskId: $taskId, contextId: $contextId, artifact: $artifact, append: $append, lastChunk: $lastChunk)'; +} + + +} + +/// @nodoc +abstract mixin class $TaskArtifactUpdateCopyWith<$Res> implements $EventCopyWith<$Res> { + factory $TaskArtifactUpdateCopyWith(TaskArtifactUpdate value, $Res Function(TaskArtifactUpdate) _then) = _$TaskArtifactUpdateCopyWithImpl; +@override @useResult +$Res call({ + String kind, String taskId, String contextId, Artifact artifact, bool append, bool lastChunk +}); + + +$ArtifactCopyWith<$Res> get artifact; + +} +/// @nodoc +class _$TaskArtifactUpdateCopyWithImpl<$Res> + implements $TaskArtifactUpdateCopyWith<$Res> { + _$TaskArtifactUpdateCopyWithImpl(this._self, this._then); + + final TaskArtifactUpdate _self; + final $Res Function(TaskArtifactUpdate) _then; + +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? kind = null,Object? taskId = null,Object? contextId = null,Object? artifact = null,Object? append = null,Object? lastChunk = null,}) { + return _then(TaskArtifactUpdate( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String,artifact: null == artifact ? _self.artifact : artifact // ignore: cast_nullable_to_non_nullable +as Artifact,append: null == append ? _self.append : append // ignore: cast_nullable_to_non_nullable +as bool,lastChunk: null == lastChunk ? _self.lastChunk : lastChunk // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + +/// Create a copy of Event +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$ArtifactCopyWith<$Res> get artifact { + + return $ArtifactCopyWith<$Res>(_self.artifact, (value) { + return _then(_self.copyWith(artifact: value)); + }); +} +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/events.g.dart b/packages/a2a_dart/lib/src/core/events.g.dart new file mode 100644 index 000000000..a5a023e13 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/events.g.dart @@ -0,0 +1,87 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'events.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +TaskStatusUpdateEvent _$TaskStatusUpdateEventFromJson( + Map json, +) => TaskStatusUpdateEvent( + kind: json['kind'] as String? ?? 'task_status_update', + taskId: json['taskId'] as String, + contextId: json['contextId'] as String, + status: TaskStatus.fromJson(json['status'] as Map), + final_: json['final_'] as bool, +); + +Map _$TaskStatusUpdateEventToJson( + TaskStatusUpdateEvent instance, +) => { + 'kind': instance.kind, + 'taskId': instance.taskId, + 'contextId': instance.contextId, + 'status': instance.status.toJson(), + 'final_': instance.final_, +}; + +TaskArtifactUpdateEvent _$TaskArtifactUpdateEventFromJson( + Map json, +) => TaskArtifactUpdateEvent( + kind: json['kind'] as String? ?? 'task_artifact_update', + taskId: json['taskId'] as String, + contextId: json['contextId'] as String, + artifact: Artifact.fromJson(json['artifact'] as Map), + append: json['append'] as bool, + lastChunk: json['lastChunk'] as bool, +); + +Map _$TaskArtifactUpdateEventToJson( + TaskArtifactUpdateEvent instance, +) => { + 'kind': instance.kind, + 'taskId': instance.taskId, + 'contextId': instance.contextId, + 'artifact': instance.artifact.toJson(), + 'append': instance.append, + 'lastChunk': instance.lastChunk, +}; + +TaskStatusUpdate _$TaskStatusUpdateFromJson(Map json) => + TaskStatusUpdate( + kind: json['kind'] as String? ?? 'task_status_update', + taskId: json['taskId'] as String, + contextId: json['contextId'] as String, + status: TaskStatus.fromJson(json['status'] as Map), + final_: json['final_'] as bool, + ); + +Map _$TaskStatusUpdateToJson(TaskStatusUpdate instance) => + { + 'kind': instance.kind, + 'taskId': instance.taskId, + 'contextId': instance.contextId, + 'status': instance.status.toJson(), + 'final_': instance.final_, + }; + +TaskArtifactUpdate _$TaskArtifactUpdateFromJson(Map json) => + TaskArtifactUpdate( + kind: json['kind'] as String? ?? 'task_artifact_update', + taskId: json['taskId'] as String, + contextId: json['contextId'] as String, + artifact: Artifact.fromJson(json['artifact'] as Map), + append: json['append'] as bool, + lastChunk: json['lastChunk'] as bool, + ); + +Map _$TaskArtifactUpdateToJson(TaskArtifactUpdate instance) => + { + 'kind': instance.kind, + 'taskId': instance.taskId, + 'contextId': instance.contextId, + 'artifact': instance.artifact.toJson(), + 'append': instance.append, + 'lastChunk': instance.lastChunk, + }; diff --git a/packages/a2a_dart/lib/src/core/list_tasks_params.dart b/packages/a2a_dart/lib/src/core/list_tasks_params.dart new file mode 100644 index 000000000..ca089cdc0 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/list_tasks_params.dart @@ -0,0 +1,61 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'list_tasks_result.dart'; +import 'task.dart'; + +part 'list_tasks_params.freezed.dart'; +part 'list_tasks_params.g.dart'; + +/// Defines the parameters for the `tasks/list` RPC method. +/// +/// These parameters allow clients to filter, paginate, and control the scope +/// of the task list returned by the server. +@freezed +abstract class ListTasksParams with _$ListTasksParams { + /// Creates a [ListTasksParams] instance. + const factory ListTasksParams({ + /// Optional. Filter tasks to only include those belonging to this specific + /// context ID (e.g., a conversation or session). + String? contextId, + + /// Optional. Filter tasks by their current [TaskState]. + TaskState? status, + + /// The maximum number of tasks to return in a single response. + /// + /// Must be between 1 and 100, inclusive. Defaults to 50. + @Default(50) int pageSize, + + /// An opaque token used to retrieve the next page of results. + /// + /// This should be the value of `nextPageToken` from a previous + /// [ListTasksResult]. If omitted, the first page is returned. + String? pageToken, + + /// The number of recent messages to include in each task's history. + /// + /// Must be non-negative. Defaults to 0 (no history included). + @Default(0) int historyLength, + + /// Optional. Filter tasks to include only those updated at or after this + /// timestamp (in milliseconds since the Unix epoch). + int? lastUpdatedAfter, + + /// Whether to include associated artifacts in the returned tasks. + /// + /// Defaults to `false` to minimize payload size. Set to `true` to retrieve + /// artifacts. + @Default(false) bool includeArtifacts, + + /// Optional. Request-specific metadata for extensions or custom use cases. + Map? metadata, + }) = _ListTasksParams; + + /// Deserializes a [ListTasksParams] instance from a JSON object. + factory ListTasksParams.fromJson(Map json) => + _$ListTasksParamsFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/list_tasks_params.freezed.dart b/packages/a2a_dart/lib/src/core/list_tasks_params.freezed.dart new file mode 100644 index 000000000..438467a70 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/list_tasks_params.freezed.dart @@ -0,0 +1,347 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'list_tasks_params.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$ListTasksParams { + +/// Optional. Filter tasks to only include those belonging to this specific +/// context ID (e.g., a conversation or session). + String? get contextId;/// Optional. Filter tasks by their current [TaskState]. + TaskState? get status;/// The maximum number of tasks to return in a single response. +/// +/// Must be between 1 and 100, inclusive. Defaults to 50. + int get pageSize;/// An opaque token used to retrieve the next page of results. +/// +/// This should be the value of `nextPageToken` from a previous +/// [ListTasksResult]. If omitted, the first page is returned. + String? get pageToken;/// The number of recent messages to include in each task's history. +/// +/// Must be non-negative. Defaults to 0 (no history included). + int get historyLength;/// Optional. Filter tasks to include only those updated at or after this +/// timestamp (in milliseconds since the Unix epoch). + int? get lastUpdatedAfter;/// Whether to include associated artifacts in the returned tasks. +/// +/// Defaults to `false` to minimize payload size. Set to `true` to retrieve +/// artifacts. + bool get includeArtifacts;/// Optional. Request-specific metadata for extensions or custom use cases. + Map? get metadata; +/// Create a copy of ListTasksParams +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ListTasksParamsCopyWith get copyWith => _$ListTasksParamsCopyWithImpl(this as ListTasksParams, _$identity); + + /// Serializes this ListTasksParams to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ListTasksParams&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.status, status) || other.status == status)&&(identical(other.pageSize, pageSize) || other.pageSize == pageSize)&&(identical(other.pageToken, pageToken) || other.pageToken == pageToken)&&(identical(other.historyLength, historyLength) || other.historyLength == historyLength)&&(identical(other.lastUpdatedAfter, lastUpdatedAfter) || other.lastUpdatedAfter == lastUpdatedAfter)&&(identical(other.includeArtifacts, includeArtifacts) || other.includeArtifacts == includeArtifacts)&&const DeepCollectionEquality().equals(other.metadata, metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,contextId,status,pageSize,pageToken,historyLength,lastUpdatedAfter,includeArtifacts,const DeepCollectionEquality().hash(metadata)); + +@override +String toString() { + return 'ListTasksParams(contextId: $contextId, status: $status, pageSize: $pageSize, pageToken: $pageToken, historyLength: $historyLength, lastUpdatedAfter: $lastUpdatedAfter, includeArtifacts: $includeArtifacts, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class $ListTasksParamsCopyWith<$Res> { + factory $ListTasksParamsCopyWith(ListTasksParams value, $Res Function(ListTasksParams) _then) = _$ListTasksParamsCopyWithImpl; +@useResult +$Res call({ + String? contextId, TaskState? status, int pageSize, String? pageToken, int historyLength, int? lastUpdatedAfter, bool includeArtifacts, Map? metadata +}); + + + + +} +/// @nodoc +class _$ListTasksParamsCopyWithImpl<$Res> + implements $ListTasksParamsCopyWith<$Res> { + _$ListTasksParamsCopyWithImpl(this._self, this._then); + + final ListTasksParams _self; + final $Res Function(ListTasksParams) _then; + +/// Create a copy of ListTasksParams +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? contextId = freezed,Object? status = freezed,Object? pageSize = null,Object? pageToken = freezed,Object? historyLength = null,Object? lastUpdatedAfter = freezed,Object? includeArtifacts = null,Object? metadata = freezed,}) { + return _then(_self.copyWith( +contextId: freezed == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as TaskState?,pageSize: null == pageSize ? _self.pageSize : pageSize // ignore: cast_nullable_to_non_nullable +as int,pageToken: freezed == pageToken ? _self.pageToken : pageToken // ignore: cast_nullable_to_non_nullable +as String?,historyLength: null == historyLength ? _self.historyLength : historyLength // ignore: cast_nullable_to_non_nullable +as int,lastUpdatedAfter: freezed == lastUpdatedAfter ? _self.lastUpdatedAfter : lastUpdatedAfter // ignore: cast_nullable_to_non_nullable +as int?,includeArtifacts: null == includeArtifacts ? _self.includeArtifacts : includeArtifacts // ignore: cast_nullable_to_non_nullable +as bool,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ListTasksParams]. +extension ListTasksParamsPatterns on ListTasksParams { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ListTasksParams value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ListTasksParams() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ListTasksParams value) $default,){ +final _that = this; +switch (_that) { +case _ListTasksParams(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ListTasksParams value)? $default,){ +final _that = this; +switch (_that) { +case _ListTasksParams() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String? contextId, TaskState? status, int pageSize, String? pageToken, int historyLength, int? lastUpdatedAfter, bool includeArtifacts, Map? metadata)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ListTasksParams() when $default != null: +return $default(_that.contextId,_that.status,_that.pageSize,_that.pageToken,_that.historyLength,_that.lastUpdatedAfter,_that.includeArtifacts,_that.metadata);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String? contextId, TaskState? status, int pageSize, String? pageToken, int historyLength, int? lastUpdatedAfter, bool includeArtifacts, Map? metadata) $default,) {final _that = this; +switch (_that) { +case _ListTasksParams(): +return $default(_that.contextId,_that.status,_that.pageSize,_that.pageToken,_that.historyLength,_that.lastUpdatedAfter,_that.includeArtifacts,_that.metadata);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String? contextId, TaskState? status, int pageSize, String? pageToken, int historyLength, int? lastUpdatedAfter, bool includeArtifacts, Map? metadata)? $default,) {final _that = this; +switch (_that) { +case _ListTasksParams() when $default != null: +return $default(_that.contextId,_that.status,_that.pageSize,_that.pageToken,_that.historyLength,_that.lastUpdatedAfter,_that.includeArtifacts,_that.metadata);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _ListTasksParams implements ListTasksParams { + const _ListTasksParams({this.contextId, this.status, this.pageSize = 50, this.pageToken, this.historyLength = 0, this.lastUpdatedAfter, this.includeArtifacts = false, final Map? metadata}): _metadata = metadata; + factory _ListTasksParams.fromJson(Map json) => _$ListTasksParamsFromJson(json); + +/// Optional. Filter tasks to only include those belonging to this specific +/// context ID (e.g., a conversation or session). +@override final String? contextId; +/// Optional. Filter tasks by their current [TaskState]. +@override final TaskState? status; +/// The maximum number of tasks to return in a single response. +/// +/// Must be between 1 and 100, inclusive. Defaults to 50. +@override@JsonKey() final int pageSize; +/// An opaque token used to retrieve the next page of results. +/// +/// This should be the value of `nextPageToken` from a previous +/// [ListTasksResult]. If omitted, the first page is returned. +@override final String? pageToken; +/// The number of recent messages to include in each task's history. +/// +/// Must be non-negative. Defaults to 0 (no history included). +@override@JsonKey() final int historyLength; +/// Optional. Filter tasks to include only those updated at or after this +/// timestamp (in milliseconds since the Unix epoch). +@override final int? lastUpdatedAfter; +/// Whether to include associated artifacts in the returned tasks. +/// +/// Defaults to `false` to minimize payload size. Set to `true` to retrieve +/// artifacts. +@override@JsonKey() final bool includeArtifacts; +/// Optional. Request-specific metadata for extensions or custom use cases. + final Map? _metadata; +/// Optional. Request-specific metadata for extensions or custom use cases. +@override Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +/// Create a copy of ListTasksParams +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ListTasksParamsCopyWith<_ListTasksParams> get copyWith => __$ListTasksParamsCopyWithImpl<_ListTasksParams>(this, _$identity); + +@override +Map toJson() { + return _$ListTasksParamsToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ListTasksParams&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.status, status) || other.status == status)&&(identical(other.pageSize, pageSize) || other.pageSize == pageSize)&&(identical(other.pageToken, pageToken) || other.pageToken == pageToken)&&(identical(other.historyLength, historyLength) || other.historyLength == historyLength)&&(identical(other.lastUpdatedAfter, lastUpdatedAfter) || other.lastUpdatedAfter == lastUpdatedAfter)&&(identical(other.includeArtifacts, includeArtifacts) || other.includeArtifacts == includeArtifacts)&&const DeepCollectionEquality().equals(other._metadata, _metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,contextId,status,pageSize,pageToken,historyLength,lastUpdatedAfter,includeArtifacts,const DeepCollectionEquality().hash(_metadata)); + +@override +String toString() { + return 'ListTasksParams(contextId: $contextId, status: $status, pageSize: $pageSize, pageToken: $pageToken, historyLength: $historyLength, lastUpdatedAfter: $lastUpdatedAfter, includeArtifacts: $includeArtifacts, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class _$ListTasksParamsCopyWith<$Res> implements $ListTasksParamsCopyWith<$Res> { + factory _$ListTasksParamsCopyWith(_ListTasksParams value, $Res Function(_ListTasksParams) _then) = __$ListTasksParamsCopyWithImpl; +@override @useResult +$Res call({ + String? contextId, TaskState? status, int pageSize, String? pageToken, int historyLength, int? lastUpdatedAfter, bool includeArtifacts, Map? metadata +}); + + + + +} +/// @nodoc +class __$ListTasksParamsCopyWithImpl<$Res> + implements _$ListTasksParamsCopyWith<$Res> { + __$ListTasksParamsCopyWithImpl(this._self, this._then); + + final _ListTasksParams _self; + final $Res Function(_ListTasksParams) _then; + +/// Create a copy of ListTasksParams +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? contextId = freezed,Object? status = freezed,Object? pageSize = null,Object? pageToken = freezed,Object? historyLength = null,Object? lastUpdatedAfter = freezed,Object? includeArtifacts = null,Object? metadata = freezed,}) { + return _then(_ListTasksParams( +contextId: freezed == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as TaskState?,pageSize: null == pageSize ? _self.pageSize : pageSize // ignore: cast_nullable_to_non_nullable +as int,pageToken: freezed == pageToken ? _self.pageToken : pageToken // ignore: cast_nullable_to_non_nullable +as String?,historyLength: null == historyLength ? _self.historyLength : historyLength // ignore: cast_nullable_to_non_nullable +as int,lastUpdatedAfter: freezed == lastUpdatedAfter ? _self.lastUpdatedAfter : lastUpdatedAfter // ignore: cast_nullable_to_non_nullable +as int?,includeArtifacts: null == includeArtifacts ? _self.includeArtifacts : includeArtifacts // ignore: cast_nullable_to_non_nullable +as bool,metadata: freezed == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/list_tasks_params.g.dart b/packages/a2a_dart/lib/src/core/list_tasks_params.g.dart new file mode 100644 index 000000000..b051a9e6f --- /dev/null +++ b/packages/a2a_dart/lib/src/core/list_tasks_params.g.dart @@ -0,0 +1,43 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'list_tasks_params.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_ListTasksParams _$ListTasksParamsFromJson(Map json) => + _ListTasksParams( + contextId: json['contextId'] as String?, + status: $enumDecodeNullable(_$TaskStateEnumMap, json['status']), + pageSize: (json['pageSize'] as num?)?.toInt() ?? 50, + pageToken: json['pageToken'] as String?, + historyLength: (json['historyLength'] as num?)?.toInt() ?? 0, + lastUpdatedAfter: (json['lastUpdatedAfter'] as num?)?.toInt(), + includeArtifacts: json['includeArtifacts'] as bool? ?? false, + metadata: json['metadata'] as Map?, + ); + +Map _$ListTasksParamsToJson(_ListTasksParams instance) => + { + 'contextId': instance.contextId, + 'status': _$TaskStateEnumMap[instance.status], + 'pageSize': instance.pageSize, + 'pageToken': instance.pageToken, + 'historyLength': instance.historyLength, + 'lastUpdatedAfter': instance.lastUpdatedAfter, + 'includeArtifacts': instance.includeArtifacts, + 'metadata': instance.metadata, + }; + +const _$TaskStateEnumMap = { + TaskState.submitted: 'submitted', + TaskState.working: 'working', + TaskState.inputRequired: 'inputRequired', + TaskState.completed: 'completed', + TaskState.canceled: 'canceled', + TaskState.failed: 'failed', + TaskState.rejected: 'rejected', + TaskState.authRequired: 'authRequired', + TaskState.unknown: 'unknown', +}; diff --git a/packages/a2a_dart/lib/src/core/list_tasks_result.dart b/packages/a2a_dart/lib/src/core/list_tasks_result.dart new file mode 100644 index 000000000..aee9df2a3 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/list_tasks_result.dart @@ -0,0 +1,39 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'task.dart'; + +part 'list_tasks_result.freezed.dart'; +part 'list_tasks_result.g.dart'; + +/// Represents the response from the `tasks/list` RPC method. +/// +/// Contains a paginated list of tasks matching the request criteria. +@freezed +abstract class ListTasksResult with _$ListTasksResult { + /// Creates a [ListTasksResult] instance. + const factory ListTasksResult({ + /// The list of [Task] objects matching the specified filters and + /// pagination. + required List tasks, + + /// The total number of tasks available on the server that match the filter + /// criteria (ignoring pagination). + required int totalSize, + + /// The maximum number of tasks requested per page. + required int pageSize, + + /// An opaque token for retrieving the next page of results. + /// + /// If this string is empty, there are no more pages. + required String nextPageToken, + }) = _ListTasksResult; + + /// Deserializes a [ListTasksResult] instance from a JSON object. + factory ListTasksResult.fromJson(Map json) => + _$ListTasksResultFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/list_tasks_result.freezed.dart b/packages/a2a_dart/lib/src/core/list_tasks_result.freezed.dart new file mode 100644 index 000000000..36de7292f --- /dev/null +++ b/packages/a2a_dart/lib/src/core/list_tasks_result.freezed.dart @@ -0,0 +1,310 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'list_tasks_result.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$ListTasksResult { + +/// The list of [Task] objects matching the specified filters and +/// pagination. + List get tasks;/// The total number of tasks available on the server that match the filter +/// criteria (ignoring pagination). + int get totalSize;/// The maximum number of tasks requested per page. + int get pageSize;/// An opaque token for retrieving the next page of results. +/// +/// If this string is empty, there are no more pages. + String get nextPageToken; +/// Create a copy of ListTasksResult +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ListTasksResultCopyWith get copyWith => _$ListTasksResultCopyWithImpl(this as ListTasksResult, _$identity); + + /// Serializes this ListTasksResult to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ListTasksResult&&const DeepCollectionEquality().equals(other.tasks, tasks)&&(identical(other.totalSize, totalSize) || other.totalSize == totalSize)&&(identical(other.pageSize, pageSize) || other.pageSize == pageSize)&&(identical(other.nextPageToken, nextPageToken) || other.nextPageToken == nextPageToken)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(tasks),totalSize,pageSize,nextPageToken); + +@override +String toString() { + return 'ListTasksResult(tasks: $tasks, totalSize: $totalSize, pageSize: $pageSize, nextPageToken: $nextPageToken)'; +} + + +} + +/// @nodoc +abstract mixin class $ListTasksResultCopyWith<$Res> { + factory $ListTasksResultCopyWith(ListTasksResult value, $Res Function(ListTasksResult) _then) = _$ListTasksResultCopyWithImpl; +@useResult +$Res call({ + List tasks, int totalSize, int pageSize, String nextPageToken +}); + + + + +} +/// @nodoc +class _$ListTasksResultCopyWithImpl<$Res> + implements $ListTasksResultCopyWith<$Res> { + _$ListTasksResultCopyWithImpl(this._self, this._then); + + final ListTasksResult _self; + final $Res Function(ListTasksResult) _then; + +/// Create a copy of ListTasksResult +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? tasks = null,Object? totalSize = null,Object? pageSize = null,Object? nextPageToken = null,}) { + return _then(_self.copyWith( +tasks: null == tasks ? _self.tasks : tasks // ignore: cast_nullable_to_non_nullable +as List,totalSize: null == totalSize ? _self.totalSize : totalSize // ignore: cast_nullable_to_non_nullable +as int,pageSize: null == pageSize ? _self.pageSize : pageSize // ignore: cast_nullable_to_non_nullable +as int,nextPageToken: null == nextPageToken ? _self.nextPageToken : nextPageToken // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [ListTasksResult]. +extension ListTasksResultPatterns on ListTasksResult { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ListTasksResult value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ListTasksResult() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ListTasksResult value) $default,){ +final _that = this; +switch (_that) { +case _ListTasksResult(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ListTasksResult value)? $default,){ +final _that = this; +switch (_that) { +case _ListTasksResult() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List tasks, int totalSize, int pageSize, String nextPageToken)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ListTasksResult() when $default != null: +return $default(_that.tasks,_that.totalSize,_that.pageSize,_that.nextPageToken);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List tasks, int totalSize, int pageSize, String nextPageToken) $default,) {final _that = this; +switch (_that) { +case _ListTasksResult(): +return $default(_that.tasks,_that.totalSize,_that.pageSize,_that.nextPageToken);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List tasks, int totalSize, int pageSize, String nextPageToken)? $default,) {final _that = this; +switch (_that) { +case _ListTasksResult() when $default != null: +return $default(_that.tasks,_that.totalSize,_that.pageSize,_that.nextPageToken);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _ListTasksResult implements ListTasksResult { + const _ListTasksResult({required final List tasks, required this.totalSize, required this.pageSize, required this.nextPageToken}): _tasks = tasks; + factory _ListTasksResult.fromJson(Map json) => _$ListTasksResultFromJson(json); + +/// The list of [Task] objects matching the specified filters and +/// pagination. + final List _tasks; +/// The list of [Task] objects matching the specified filters and +/// pagination. +@override List get tasks { + if (_tasks is EqualUnmodifiableListView) return _tasks; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_tasks); +} + +/// The total number of tasks available on the server that match the filter +/// criteria (ignoring pagination). +@override final int totalSize; +/// The maximum number of tasks requested per page. +@override final int pageSize; +/// An opaque token for retrieving the next page of results. +/// +/// If this string is empty, there are no more pages. +@override final String nextPageToken; + +/// Create a copy of ListTasksResult +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ListTasksResultCopyWith<_ListTasksResult> get copyWith => __$ListTasksResultCopyWithImpl<_ListTasksResult>(this, _$identity); + +@override +Map toJson() { + return _$ListTasksResultToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ListTasksResult&&const DeepCollectionEquality().equals(other._tasks, _tasks)&&(identical(other.totalSize, totalSize) || other.totalSize == totalSize)&&(identical(other.pageSize, pageSize) || other.pageSize == pageSize)&&(identical(other.nextPageToken, nextPageToken) || other.nextPageToken == nextPageToken)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_tasks),totalSize,pageSize,nextPageToken); + +@override +String toString() { + return 'ListTasksResult(tasks: $tasks, totalSize: $totalSize, pageSize: $pageSize, nextPageToken: $nextPageToken)'; +} + + +} + +/// @nodoc +abstract mixin class _$ListTasksResultCopyWith<$Res> implements $ListTasksResultCopyWith<$Res> { + factory _$ListTasksResultCopyWith(_ListTasksResult value, $Res Function(_ListTasksResult) _then) = __$ListTasksResultCopyWithImpl; +@override @useResult +$Res call({ + List tasks, int totalSize, int pageSize, String nextPageToken +}); + + + + +} +/// @nodoc +class __$ListTasksResultCopyWithImpl<$Res> + implements _$ListTasksResultCopyWith<$Res> { + __$ListTasksResultCopyWithImpl(this._self, this._then); + + final _ListTasksResult _self; + final $Res Function(_ListTasksResult) _then; + +/// Create a copy of ListTasksResult +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? tasks = null,Object? totalSize = null,Object? pageSize = null,Object? nextPageToken = null,}) { + return _then(_ListTasksResult( +tasks: null == tasks ? _self._tasks : tasks // ignore: cast_nullable_to_non_nullable +as List,totalSize: null == totalSize ? _self.totalSize : totalSize // ignore: cast_nullable_to_non_nullable +as int,pageSize: null == pageSize ? _self.pageSize : pageSize // ignore: cast_nullable_to_non_nullable +as int,nextPageToken: null == nextPageToken ? _self.nextPageToken : nextPageToken // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/list_tasks_result.g.dart b/packages/a2a_dart/lib/src/core/list_tasks_result.g.dart new file mode 100644 index 000000000..8d8ba2cad --- /dev/null +++ b/packages/a2a_dart/lib/src/core/list_tasks_result.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'list_tasks_result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_ListTasksResult _$ListTasksResultFromJson(Map json) => + _ListTasksResult( + tasks: (json['tasks'] as List) + .map((e) => Task.fromJson(e as Map)) + .toList(), + totalSize: (json['totalSize'] as num).toInt(), + pageSize: (json['pageSize'] as num).toInt(), + nextPageToken: json['nextPageToken'] as String, + ); + +Map _$ListTasksResultToJson(_ListTasksResult instance) => + { + 'tasks': instance.tasks.map((e) => e.toJson()).toList(), + 'totalSize': instance.totalSize, + 'pageSize': instance.pageSize, + 'nextPageToken': instance.nextPageToken, + }; diff --git a/packages/a2a_dart/lib/src/core/message.dart b/packages/a2a_dart/lib/src/core/message.dart new file mode 100644 index 000000000..4badba8af --- /dev/null +++ b/packages/a2a_dart/lib/src/core/message.dart @@ -0,0 +1,70 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'part.dart'; + +part 'message.freezed.dart'; +part 'message.g.dart'; + +/// Identifies the sender of a [Message]. +enum Role { + /// The message originated from the user (i.e., the A2A client). + user, + + /// The message originated from the agent (i.e., the A2A server). + agent, +} + +/// Represents a single communication exchange within an A2A interaction. +/// +/// Messages are the fundamental unit of communication, used for sending +/// instructions, prompts, data, and replies between a client and an agent. +/// A message consists of one or more [Part]s, allowing for rich content. +@freezed +abstract class Message with _$Message { + /// Creates a [Message] instance. + const factory Message({ + /// Specifies the sender of the message, either [Role.user] or [Role.agent]. + required Role role, + + /// A list of content [Part]s that make up the message body. + /// + /// A message can be composed of multiple parts of different types + /// (e.g., text, files, structured data). + required List parts, + + /// Optional metadata for extensions, as a map where the key is an + /// extension-specific identifier. + Map? metadata, + + /// Optional list of URIs for extensions that are relevant to this message. + List? extensions, + + /// Optional list of other task IDs that this message references for + /// additional context. + List? referenceTaskIds, + + /// A unique identifier for this message, typically a UUID, generated by the + /// sender. + required String messageId, + + /// The ID of the task this message belongs to. + /// + /// This can be omitted for the initial message in a new task interaction. + String? taskId, + + /// An identifier used to group related messages and tasks, such as within + /// a single conversation or session. + String? contextId, + + /// The type discriminator for this object, always 'message'. + @Default('message') String kind, + }) = _Message; + + /// Deserializes a [Message] instance from a JSON object. + factory Message.fromJson(Map json) => + _$MessageFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/message.freezed.dart b/packages/a2a_dart/lib/src/core/message.freezed.dart new file mode 100644 index 000000000..5fc55f68e --- /dev/null +++ b/packages/a2a_dart/lib/src/core/message.freezed.dart @@ -0,0 +1,376 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'message.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$Message { + +/// Specifies the sender of the message, either [Role.user] or [Role.agent]. + Role get role;/// A list of content [Part]s that make up the message body. +/// +/// A message can be composed of multiple parts of different types +/// (e.g., text, files, structured data). + List get parts;/// Optional metadata for extensions, as a map where the key is an +/// extension-specific identifier. + Map? get metadata;/// Optional list of URIs for extensions that are relevant to this message. + List? get extensions;/// Optional list of other task IDs that this message references for +/// additional context. + List? get referenceTaskIds;/// A unique identifier for this message, typically a UUID, generated by the +/// sender. + String get messageId;/// The ID of the task this message belongs to. +/// +/// This can be omitted for the initial message in a new task interaction. + String? get taskId;/// An identifier used to group related messages and tasks, such as within +/// a single conversation or session. + String? get contextId;/// The type discriminator for this object, always 'message'. + String get kind; +/// Create a copy of Message +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$MessageCopyWith get copyWith => _$MessageCopyWithImpl(this as Message, _$identity); + + /// Serializes this Message to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Message&&(identical(other.role, role) || other.role == role)&&const DeepCollectionEquality().equals(other.parts, parts)&&const DeepCollectionEquality().equals(other.metadata, metadata)&&const DeepCollectionEquality().equals(other.extensions, extensions)&&const DeepCollectionEquality().equals(other.referenceTaskIds, referenceTaskIds)&&(identical(other.messageId, messageId) || other.messageId == messageId)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.kind, kind) || other.kind == kind)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,role,const DeepCollectionEquality().hash(parts),const DeepCollectionEquality().hash(metadata),const DeepCollectionEquality().hash(extensions),const DeepCollectionEquality().hash(referenceTaskIds),messageId,taskId,contextId,kind); + +@override +String toString() { + return 'Message(role: $role, parts: $parts, metadata: $metadata, extensions: $extensions, referenceTaskIds: $referenceTaskIds, messageId: $messageId, taskId: $taskId, contextId: $contextId, kind: $kind)'; +} + + +} + +/// @nodoc +abstract mixin class $MessageCopyWith<$Res> { + factory $MessageCopyWith(Message value, $Res Function(Message) _then) = _$MessageCopyWithImpl; +@useResult +$Res call({ + Role role, List parts, Map? metadata, List? extensions, List? referenceTaskIds, String messageId, String? taskId, String? contextId, String kind +}); + + + + +} +/// @nodoc +class _$MessageCopyWithImpl<$Res> + implements $MessageCopyWith<$Res> { + _$MessageCopyWithImpl(this._self, this._then); + + final Message _self; + final $Res Function(Message) _then; + +/// Create a copy of Message +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? role = null,Object? parts = null,Object? metadata = freezed,Object? extensions = freezed,Object? referenceTaskIds = freezed,Object? messageId = null,Object? taskId = freezed,Object? contextId = freezed,Object? kind = null,}) { + return _then(_self.copyWith( +role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable +as Role,parts: null == parts ? _self.parts : parts // ignore: cast_nullable_to_non_nullable +as List,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?,extensions: freezed == extensions ? _self.extensions : extensions // ignore: cast_nullable_to_non_nullable +as List?,referenceTaskIds: freezed == referenceTaskIds ? _self.referenceTaskIds : referenceTaskIds // ignore: cast_nullable_to_non_nullable +as List?,messageId: null == messageId ? _self.messageId : messageId // ignore: cast_nullable_to_non_nullable +as String,taskId: freezed == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String?,contextId: freezed == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String?,kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [Message]. +extension MessagePatterns on Message { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _Message value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _Message() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _Message value) $default,){ +final _that = this; +switch (_that) { +case _Message(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _Message value)? $default,){ +final _that = this; +switch (_that) { +case _Message() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( Role role, List parts, Map? metadata, List? extensions, List? referenceTaskIds, String messageId, String? taskId, String? contextId, String kind)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _Message() when $default != null: +return $default(_that.role,_that.parts,_that.metadata,_that.extensions,_that.referenceTaskIds,_that.messageId,_that.taskId,_that.contextId,_that.kind);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( Role role, List parts, Map? metadata, List? extensions, List? referenceTaskIds, String messageId, String? taskId, String? contextId, String kind) $default,) {final _that = this; +switch (_that) { +case _Message(): +return $default(_that.role,_that.parts,_that.metadata,_that.extensions,_that.referenceTaskIds,_that.messageId,_that.taskId,_that.contextId,_that.kind);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( Role role, List parts, Map? metadata, List? extensions, List? referenceTaskIds, String messageId, String? taskId, String? contextId, String kind)? $default,) {final _that = this; +switch (_that) { +case _Message() when $default != null: +return $default(_that.role,_that.parts,_that.metadata,_that.extensions,_that.referenceTaskIds,_that.messageId,_that.taskId,_that.contextId,_that.kind);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _Message implements Message { + const _Message({required this.role, required final List parts, final Map? metadata, final List? extensions, final List? referenceTaskIds, required this.messageId, this.taskId, this.contextId, this.kind = 'message'}): _parts = parts,_metadata = metadata,_extensions = extensions,_referenceTaskIds = referenceTaskIds; + factory _Message.fromJson(Map json) => _$MessageFromJson(json); + +/// Specifies the sender of the message, either [Role.user] or [Role.agent]. +@override final Role role; +/// A list of content [Part]s that make up the message body. +/// +/// A message can be composed of multiple parts of different types +/// (e.g., text, files, structured data). + final List _parts; +/// A list of content [Part]s that make up the message body. +/// +/// A message can be composed of multiple parts of different types +/// (e.g., text, files, structured data). +@override List get parts { + if (_parts is EqualUnmodifiableListView) return _parts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_parts); +} + +/// Optional metadata for extensions, as a map where the key is an +/// extension-specific identifier. + final Map? _metadata; +/// Optional metadata for extensions, as a map where the key is an +/// extension-specific identifier. +@override Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + +/// Optional list of URIs for extensions that are relevant to this message. + final List? _extensions; +/// Optional list of URIs for extensions that are relevant to this message. +@override List? get extensions { + final value = _extensions; + if (value == null) return null; + if (_extensions is EqualUnmodifiableListView) return _extensions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// Optional list of other task IDs that this message references for +/// additional context. + final List? _referenceTaskIds; +/// Optional list of other task IDs that this message references for +/// additional context. +@override List? get referenceTaskIds { + final value = _referenceTaskIds; + if (value == null) return null; + if (_referenceTaskIds is EqualUnmodifiableListView) return _referenceTaskIds; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// A unique identifier for this message, typically a UUID, generated by the +/// sender. +@override final String messageId; +/// The ID of the task this message belongs to. +/// +/// This can be omitted for the initial message in a new task interaction. +@override final String? taskId; +/// An identifier used to group related messages and tasks, such as within +/// a single conversation or session. +@override final String? contextId; +/// The type discriminator for this object, always 'message'. +@override@JsonKey() final String kind; + +/// Create a copy of Message +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$MessageCopyWith<_Message> get copyWith => __$MessageCopyWithImpl<_Message>(this, _$identity); + +@override +Map toJson() { + return _$MessageToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Message&&(identical(other.role, role) || other.role == role)&&const DeepCollectionEquality().equals(other._parts, _parts)&&const DeepCollectionEquality().equals(other._metadata, _metadata)&&const DeepCollectionEquality().equals(other._extensions, _extensions)&&const DeepCollectionEquality().equals(other._referenceTaskIds, _referenceTaskIds)&&(identical(other.messageId, messageId) || other.messageId == messageId)&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.kind, kind) || other.kind == kind)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,role,const DeepCollectionEquality().hash(_parts),const DeepCollectionEquality().hash(_metadata),const DeepCollectionEquality().hash(_extensions),const DeepCollectionEquality().hash(_referenceTaskIds),messageId,taskId,contextId,kind); + +@override +String toString() { + return 'Message(role: $role, parts: $parts, metadata: $metadata, extensions: $extensions, referenceTaskIds: $referenceTaskIds, messageId: $messageId, taskId: $taskId, contextId: $contextId, kind: $kind)'; +} + + +} + +/// @nodoc +abstract mixin class _$MessageCopyWith<$Res> implements $MessageCopyWith<$Res> { + factory _$MessageCopyWith(_Message value, $Res Function(_Message) _then) = __$MessageCopyWithImpl; +@override @useResult +$Res call({ + Role role, List parts, Map? metadata, List? extensions, List? referenceTaskIds, String messageId, String? taskId, String? contextId, String kind +}); + + + + +} +/// @nodoc +class __$MessageCopyWithImpl<$Res> + implements _$MessageCopyWith<$Res> { + __$MessageCopyWithImpl(this._self, this._then); + + final _Message _self; + final $Res Function(_Message) _then; + +/// Create a copy of Message +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? role = null,Object? parts = null,Object? metadata = freezed,Object? extensions = freezed,Object? referenceTaskIds = freezed,Object? messageId = null,Object? taskId = freezed,Object? contextId = freezed,Object? kind = null,}) { + return _then(_Message( +role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable +as Role,parts: null == parts ? _self._parts : parts // ignore: cast_nullable_to_non_nullable +as List,metadata: freezed == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?,extensions: freezed == extensions ? _self._extensions : extensions // ignore: cast_nullable_to_non_nullable +as List?,referenceTaskIds: freezed == referenceTaskIds ? _self._referenceTaskIds : referenceTaskIds // ignore: cast_nullable_to_non_nullable +as List?,messageId: null == messageId ? _self.messageId : messageId // ignore: cast_nullable_to_non_nullable +as String,taskId: freezed == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String?,contextId: freezed == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String?,kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/message.g.dart b/packages/a2a_dart/lib/src/core/message.g.dart new file mode 100644 index 000000000..e49a607fa --- /dev/null +++ b/packages/a2a_dart/lib/src/core/message.g.dart @@ -0,0 +1,39 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'message.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_Message _$MessageFromJson(Map json) => _Message( + role: $enumDecode(_$RoleEnumMap, json['role']), + parts: (json['parts'] as List) + .map((e) => Part.fromJson(e as Map)) + .toList(), + metadata: json['metadata'] as Map?, + extensions: (json['extensions'] as List?) + ?.map((e) => e as String) + .toList(), + referenceTaskIds: (json['referenceTaskIds'] as List?) + ?.map((e) => e as String) + .toList(), + messageId: json['messageId'] as String, + taskId: json['taskId'] as String?, + contextId: json['contextId'] as String?, + kind: json['kind'] as String? ?? 'message', +); + +Map _$MessageToJson(_Message instance) => { + 'role': _$RoleEnumMap[instance.role]!, + 'parts': instance.parts.map((e) => e.toJson()).toList(), + 'metadata': instance.metadata, + 'extensions': instance.extensions, + 'referenceTaskIds': instance.referenceTaskIds, + 'messageId': instance.messageId, + 'taskId': instance.taskId, + 'contextId': instance.contextId, + 'kind': instance.kind, +}; + +const _$RoleEnumMap = {Role.user: 'user', Role.agent: 'agent'}; diff --git a/packages/a2a_dart/lib/src/core/part.dart b/packages/a2a_dart/lib/src/core/part.dart new file mode 100644 index 000000000..91bcdaa07 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/part.dart @@ -0,0 +1,93 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// @docImport 'message.dart'; +library; + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'part.freezed.dart'; +part 'part.g.dart'; + +/// Represents a distinct piece of content within a [Message] or Artifact. +/// +/// A [Part] can be text, a file reference, or structured data. The `kind` field +/// acts as a discriminator to determine the specific type of the content part. +@Freezed(unionKey: 'kind', unionValueCase: FreezedUnionCase.snake) +abstract class Part with _$Part { + /// Represents a plain text content part. + const factory Part.text({ + /// The type discriminator, always 'text'. + @Default('text') String kind, + + /// The string content. + required String text, + + /// Optional metadata associated with this text part. + Map? metadata, + }) = TextPart; + + /// Represents a file content part. + const factory Part.file({ + /// The type discriminator, always 'file'. + @Default('file') String kind, + + /// The file details, specifying the file's location (URI) or content + /// (bytes). + @JsonKey(name: 'data') required FileType file, + + /// Optional metadata associated with this file part. + Map? metadata, + }) = FilePart; + + /// Represents a structured JSON data content part. + const factory Part.data({ + /// The type discriminator, always 'data'. + @Default('data') String kind, + + /// The structured data, represented as a map. + required Map data, + + /// Optional metadata associated with this data part. + Map? metadata, + }) = DataPart; + + /// Deserializes a [Part] instance from a JSON object. + factory Part.fromJson(Map json) => _$PartFromJson(json); +} + +/// Represents file data, used within a [FilePart]. +/// +/// The file content can be provided either as a URI pointing to the file or +/// directly as base64-encoded bytes. +@Freezed(unionKey: 'type') +abstract class FileType with _$FileType { + /// Represents a file located at a specific URI. + const factory FileType.uri({ + /// The Uniform Resource Identifier (URI) pointing to the file's content. + required String uri, + + /// An optional name for the file (e.g., "document.pdf"). + String? name, + + /// The MIME type of the file (e.g., "application/pdf"), if known. + String? mimeType, + }) = FileWithUri; + + /// Represents a file with its content embedded as a base64-encoded string. + const factory FileType.bytes({ + /// The base64-encoded binary content of the file. + required String bytes, + + /// An optional name for the file (e.g., "image.png"). + String? name, + + /// The MIME type of the file (e.g., "image/png"), if known. + String? mimeType, + }) = FileWithBytes; + + /// Deserializes a [FileType] instance from a JSON object. + factory FileType.fromJson(Map json) => + _$FileTypeFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/part.freezed.dart b/packages/a2a_dart/lib/src/core/part.freezed.dart new file mode 100644 index 000000000..8e5e297ce --- /dev/null +++ b/packages/a2a_dart/lib/src/core/part.freezed.dart @@ -0,0 +1,908 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'part.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +Part _$PartFromJson( + Map json +) { + switch (json['kind']) { + case 'text': + return TextPart.fromJson( + json + ); + case 'file': + return FilePart.fromJson( + json + ); + case 'data': + return DataPart.fromJson( + json + ); + + default: + throw CheckedFromJsonException( + json, + 'kind', + 'Part', + 'Invalid union type "${json['kind']}"!' +); + } + +} + +/// @nodoc +mixin _$Part { + +/// The type discriminator, always 'text'. + String get kind;/// Optional metadata associated with this text part. + Map? get metadata; +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$PartCopyWith get copyWith => _$PartCopyWithImpl(this as Part, _$identity); + + /// Serializes this Part to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Part&&(identical(other.kind, kind) || other.kind == kind)&&const DeepCollectionEquality().equals(other.metadata, metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,const DeepCollectionEquality().hash(metadata)); + +@override +String toString() { + return 'Part(kind: $kind, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class $PartCopyWith<$Res> { + factory $PartCopyWith(Part value, $Res Function(Part) _then) = _$PartCopyWithImpl; +@useResult +$Res call({ + String kind, Map? metadata +}); + + + + +} +/// @nodoc +class _$PartCopyWithImpl<$Res> + implements $PartCopyWith<$Res> { + _$PartCopyWithImpl(this._self, this._then); + + final Part _self; + final $Res Function(Part) _then; + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? kind = null,Object? metadata = freezed,}) { + return _then(_self.copyWith( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [Part]. +extension PartPatterns on Part { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( TextPart value)? text,TResult Function( FilePart value)? file,TResult Function( DataPart value)? data,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case TextPart() when text != null: +return text(_that);case FilePart() when file != null: +return file(_that);case DataPart() when data != null: +return data(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( TextPart value) text,required TResult Function( FilePart value) file,required TResult Function( DataPart value) data,}){ +final _that = this; +switch (_that) { +case TextPart(): +return text(_that);case FilePart(): +return file(_that);case DataPart(): +return data(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( TextPart value)? text,TResult? Function( FilePart value)? file,TResult? Function( DataPart value)? data,}){ +final _that = this; +switch (_that) { +case TextPart() when text != null: +return text(_that);case FilePart() when file != null: +return file(_that);case DataPart() when data != null: +return data(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( String kind, String text, Map? metadata)? text,TResult Function( String kind, FileType file, Map? metadata)? file,TResult Function( String kind, Map data, Map? metadata)? data,required TResult orElse(),}) {final _that = this; +switch (_that) { +case TextPart() when text != null: +return text(_that.kind,_that.text,_that.metadata);case FilePart() when file != null: +return file(_that.kind,_that.file,_that.metadata);case DataPart() when data != null: +return data(_that.kind,_that.data,_that.metadata);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( String kind, String text, Map? metadata) text,required TResult Function( String kind, FileType file, Map? metadata) file,required TResult Function( String kind, Map data, Map? metadata) data,}) {final _that = this; +switch (_that) { +case TextPart(): +return text(_that.kind,_that.text,_that.metadata);case FilePart(): +return file(_that.kind,_that.file,_that.metadata);case DataPart(): +return data(_that.kind,_that.data,_that.metadata);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( String kind, String text, Map? metadata)? text,TResult? Function( String kind, FileType file, Map? metadata)? file,TResult? Function( String kind, Map data, Map? metadata)? data,}) {final _that = this; +switch (_that) { +case TextPart() when text != null: +return text(_that.kind,_that.text,_that.metadata);case FilePart() when file != null: +return file(_that.kind,_that.file,_that.metadata);case DataPart() when data != null: +return data(_that.kind,_that.data,_that.metadata);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class TextPart implements Part { + const TextPart({this.kind = 'text', required this.text, final Map? metadata}): _metadata = metadata; + factory TextPart.fromJson(Map json) => _$TextPartFromJson(json); + +/// The type discriminator, always 'text'. +@override@JsonKey() final String kind; +/// The string content. + final String text; +/// Optional metadata associated with this text part. + final Map? _metadata; +/// Optional metadata associated with this text part. +@override Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TextPartCopyWith get copyWith => _$TextPartCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$TextPartToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TextPart&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.text, text) || other.text == text)&&const DeepCollectionEquality().equals(other._metadata, _metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,text,const DeepCollectionEquality().hash(_metadata)); + +@override +String toString() { + return 'Part.text(kind: $kind, text: $text, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class $TextPartCopyWith<$Res> implements $PartCopyWith<$Res> { + factory $TextPartCopyWith(TextPart value, $Res Function(TextPart) _then) = _$TextPartCopyWithImpl; +@override @useResult +$Res call({ + String kind, String text, Map? metadata +}); + + + + +} +/// @nodoc +class _$TextPartCopyWithImpl<$Res> + implements $TextPartCopyWith<$Res> { + _$TextPartCopyWithImpl(this._self, this._then); + + final TextPart _self; + final $Res Function(TextPart) _then; + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? kind = null,Object? text = null,Object? metadata = freezed,}) { + return _then(TextPart( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,text: null == text ? _self.text : text // ignore: cast_nullable_to_non_nullable +as String,metadata: freezed == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class FilePart implements Part { + const FilePart({this.kind = 'file', required this.file, final Map? metadata}): _metadata = metadata; + factory FilePart.fromJson(Map json) => _$FilePartFromJson(json); + +/// The type discriminator, always 'file'. +@override@JsonKey() final String kind; +/// The file details, specifying the file's location (URI) or content +/// (bytes). + final FileType file; +/// Optional metadata associated with this file part. + final Map? _metadata; +/// Optional metadata associated with this file part. +@override Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$FilePartCopyWith get copyWith => _$FilePartCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$FilePartToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is FilePart&&(identical(other.kind, kind) || other.kind == kind)&&(identical(other.file, file) || other.file == file)&&const DeepCollectionEquality().equals(other._metadata, _metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,file,const DeepCollectionEquality().hash(_metadata)); + +@override +String toString() { + return 'Part.file(kind: $kind, file: $file, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class $FilePartCopyWith<$Res> implements $PartCopyWith<$Res> { + factory $FilePartCopyWith(FilePart value, $Res Function(FilePart) _then) = _$FilePartCopyWithImpl; +@override @useResult +$Res call({ + String kind, FileType file, Map? metadata +}); + + +$FileTypeCopyWith<$Res> get file; + +} +/// @nodoc +class _$FilePartCopyWithImpl<$Res> + implements $FilePartCopyWith<$Res> { + _$FilePartCopyWithImpl(this._self, this._then); + + final FilePart _self; + final $Res Function(FilePart) _then; + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? kind = null,Object? file = null,Object? metadata = freezed,}) { + return _then(FilePart( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,file: null == file ? _self.file : file // ignore: cast_nullable_to_non_nullable +as FileType,metadata: freezed == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$FileTypeCopyWith<$Res> get file { + + return $FileTypeCopyWith<$Res>(_self.file, (value) { + return _then(_self.copyWith(file: value)); + }); +} +} + +/// @nodoc +@JsonSerializable() + +class DataPart implements Part { + const DataPart({this.kind = 'data', required final Map data, final Map? metadata}): _data = data,_metadata = metadata; + factory DataPart.fromJson(Map json) => _$DataPartFromJson(json); + +/// The type discriminator, always 'data'. +@override@JsonKey() final String kind; +/// The structured data, represented as a map. + final Map _data; +/// The structured data, represented as a map. + Map get data { + if (_data is EqualUnmodifiableMapView) return _data; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_data); +} + +/// Optional metadata associated with this data part. + final Map? _metadata; +/// Optional metadata associated with this data part. +@override Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$DataPartCopyWith get copyWith => _$DataPartCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$DataPartToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is DataPart&&(identical(other.kind, kind) || other.kind == kind)&&const DeepCollectionEquality().equals(other._data, _data)&&const DeepCollectionEquality().equals(other._metadata, _metadata)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,kind,const DeepCollectionEquality().hash(_data),const DeepCollectionEquality().hash(_metadata)); + +@override +String toString() { + return 'Part.data(kind: $kind, data: $data, metadata: $metadata)'; +} + + +} + +/// @nodoc +abstract mixin class $DataPartCopyWith<$Res> implements $PartCopyWith<$Res> { + factory $DataPartCopyWith(DataPart value, $Res Function(DataPart) _then) = _$DataPartCopyWithImpl; +@override @useResult +$Res call({ + String kind, Map data, Map? metadata +}); + + + + +} +/// @nodoc +class _$DataPartCopyWithImpl<$Res> + implements $DataPartCopyWith<$Res> { + _$DataPartCopyWithImpl(this._self, this._then); + + final DataPart _self; + final $Res Function(DataPart) _then; + +/// Create a copy of Part +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? kind = null,Object? data = null,Object? metadata = freezed,}) { + return _then(DataPart( +kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String,data: null == data ? _self._data : data // ignore: cast_nullable_to_non_nullable +as Map,metadata: freezed == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?, + )); +} + + +} + +FileType _$FileTypeFromJson( + Map json +) { + switch (json['type']) { + case 'uri': + return FileWithUri.fromJson( + json + ); + case 'bytes': + return FileWithBytes.fromJson( + json + ); + + default: + throw CheckedFromJsonException( + json, + 'type', + 'FileType', + 'Invalid union type "${json['type']}"!' +); + } + +} + +/// @nodoc +mixin _$FileType { + +/// An optional name for the file (e.g., "document.pdf"). + String? get name;/// The MIME type of the file (e.g., "application/pdf"), if known. + String? get mimeType; +/// Create a copy of FileType +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$FileTypeCopyWith get copyWith => _$FileTypeCopyWithImpl(this as FileType, _$identity); + + /// Serializes this FileType to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is FileType&&(identical(other.name, name) || other.name == name)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,name,mimeType); + +@override +String toString() { + return 'FileType(name: $name, mimeType: $mimeType)'; +} + + +} + +/// @nodoc +abstract mixin class $FileTypeCopyWith<$Res> { + factory $FileTypeCopyWith(FileType value, $Res Function(FileType) _then) = _$FileTypeCopyWithImpl; +@useResult +$Res call({ + String? name, String? mimeType +}); + + + + +} +/// @nodoc +class _$FileTypeCopyWithImpl<$Res> + implements $FileTypeCopyWith<$Res> { + _$FileTypeCopyWithImpl(this._self, this._then); + + final FileType _self; + final $Res Function(FileType) _then; + +/// Create a copy of FileType +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? name = freezed,Object? mimeType = freezed,}) { + return _then(_self.copyWith( +name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String?,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [FileType]. +extension FileTypePatterns on FileType { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( FileWithUri value)? uri,TResult Function( FileWithBytes value)? bytes,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case FileWithUri() when uri != null: +return uri(_that);case FileWithBytes() when bytes != null: +return bytes(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( FileWithUri value) uri,required TResult Function( FileWithBytes value) bytes,}){ +final _that = this; +switch (_that) { +case FileWithUri(): +return uri(_that);case FileWithBytes(): +return bytes(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( FileWithUri value)? uri,TResult? Function( FileWithBytes value)? bytes,}){ +final _that = this; +switch (_that) { +case FileWithUri() when uri != null: +return uri(_that);case FileWithBytes() when bytes != null: +return bytes(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( String uri, String? name, String? mimeType)? uri,TResult Function( String bytes, String? name, String? mimeType)? bytes,required TResult orElse(),}) {final _that = this; +switch (_that) { +case FileWithUri() when uri != null: +return uri(_that.uri,_that.name,_that.mimeType);case FileWithBytes() when bytes != null: +return bytes(_that.bytes,_that.name,_that.mimeType);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( String uri, String? name, String? mimeType) uri,required TResult Function( String bytes, String? name, String? mimeType) bytes,}) {final _that = this; +switch (_that) { +case FileWithUri(): +return uri(_that.uri,_that.name,_that.mimeType);case FileWithBytes(): +return bytes(_that.bytes,_that.name,_that.mimeType);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( String uri, String? name, String? mimeType)? uri,TResult? Function( String bytes, String? name, String? mimeType)? bytes,}) {final _that = this; +switch (_that) { +case FileWithUri() when uri != null: +return uri(_that.uri,_that.name,_that.mimeType);case FileWithBytes() when bytes != null: +return bytes(_that.bytes,_that.name,_that.mimeType);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class FileWithUri implements FileType { + const FileWithUri({required this.uri, this.name, this.mimeType, final String? $type}): $type = $type ?? 'uri'; + factory FileWithUri.fromJson(Map json) => _$FileWithUriFromJson(json); + +/// The Uniform Resource Identifier (URI) pointing to the file's content. + final String uri; +/// An optional name for the file (e.g., "document.pdf"). +@override final String? name; +/// The MIME type of the file (e.g., "application/pdf"), if known. +@override final String? mimeType; + +@JsonKey(name: 'type') +final String $type; + + +/// Create a copy of FileType +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$FileWithUriCopyWith get copyWith => _$FileWithUriCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$FileWithUriToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is FileWithUri&&(identical(other.uri, uri) || other.uri == uri)&&(identical(other.name, name) || other.name == name)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,uri,name,mimeType); + +@override +String toString() { + return 'FileType.uri(uri: $uri, name: $name, mimeType: $mimeType)'; +} + + +} + +/// @nodoc +abstract mixin class $FileWithUriCopyWith<$Res> implements $FileTypeCopyWith<$Res> { + factory $FileWithUriCopyWith(FileWithUri value, $Res Function(FileWithUri) _then) = _$FileWithUriCopyWithImpl; +@override @useResult +$Res call({ + String uri, String? name, String? mimeType +}); + + + + +} +/// @nodoc +class _$FileWithUriCopyWithImpl<$Res> + implements $FileWithUriCopyWith<$Res> { + _$FileWithUriCopyWithImpl(this._self, this._then); + + final FileWithUri _self; + final $Res Function(FileWithUri) _then; + +/// Create a copy of FileType +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? uri = null,Object? name = freezed,Object? mimeType = freezed,}) { + return _then(FileWithUri( +uri: null == uri ? _self.uri : uri // ignore: cast_nullable_to_non_nullable +as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String?,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class FileWithBytes implements FileType { + const FileWithBytes({required this.bytes, this.name, this.mimeType, final String? $type}): $type = $type ?? 'bytes'; + factory FileWithBytes.fromJson(Map json) => _$FileWithBytesFromJson(json); + +/// The base64-encoded binary content of the file. + final String bytes; +/// An optional name for the file (e.g., "image.png"). +@override final String? name; +/// The MIME type of the file (e.g., "image/png"), if known. +@override final String? mimeType; + +@JsonKey(name: 'type') +final String $type; + + +/// Create a copy of FileType +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$FileWithBytesCopyWith get copyWith => _$FileWithBytesCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$FileWithBytesToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is FileWithBytes&&(identical(other.bytes, bytes) || other.bytes == bytes)&&(identical(other.name, name) || other.name == name)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,bytes,name,mimeType); + +@override +String toString() { + return 'FileType.bytes(bytes: $bytes, name: $name, mimeType: $mimeType)'; +} + + +} + +/// @nodoc +abstract mixin class $FileWithBytesCopyWith<$Res> implements $FileTypeCopyWith<$Res> { + factory $FileWithBytesCopyWith(FileWithBytes value, $Res Function(FileWithBytes) _then) = _$FileWithBytesCopyWithImpl; +@override @useResult +$Res call({ + String bytes, String? name, String? mimeType +}); + + + + +} +/// @nodoc +class _$FileWithBytesCopyWithImpl<$Res> + implements $FileWithBytesCopyWith<$Res> { + _$FileWithBytesCopyWithImpl(this._self, this._then); + + final FileWithBytes _self; + final $Res Function(FileWithBytes) _then; + +/// Create a copy of FileType +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? bytes = null,Object? name = freezed,Object? mimeType = freezed,}) { + return _then(FileWithBytes( +bytes: null == bytes ? _self.bytes : bytes // ignore: cast_nullable_to_non_nullable +as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String?,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/part.g.dart b/packages/a2a_dart/lib/src/core/part.g.dart new file mode 100644 index 000000000..2701febc8 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/part.g.dart @@ -0,0 +1,74 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'part.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +TextPart _$TextPartFromJson(Map json) => TextPart( + kind: json['kind'] as String? ?? 'text', + text: json['text'] as String, + metadata: json['metadata'] as Map?, +); + +Map _$TextPartToJson(TextPart instance) => { + 'kind': instance.kind, + 'text': instance.text, + 'metadata': instance.metadata, +}; + +FilePart _$FilePartFromJson(Map json) => FilePart( + kind: json['kind'] as String? ?? 'file', + file: FileType.fromJson(json['data'] as Map), + metadata: json['metadata'] as Map?, +); + +Map _$FilePartToJson(FilePart instance) => { + 'kind': instance.kind, + 'data': instance.file.toJson(), + 'metadata': instance.metadata, +}; + +DataPart _$DataPartFromJson(Map json) => DataPart( + kind: json['kind'] as String? ?? 'data', + data: json['data'] as Map, + metadata: json['metadata'] as Map?, +); + +Map _$DataPartToJson(DataPart instance) => { + 'kind': instance.kind, + 'data': instance.data, + 'metadata': instance.metadata, +}; + +FileWithUri _$FileWithUriFromJson(Map json) => FileWithUri( + uri: json['uri'] as String, + name: json['name'] as String?, + mimeType: json['mimeType'] as String?, + $type: json['type'] as String?, +); + +Map _$FileWithUriToJson(FileWithUri instance) => + { + 'uri': instance.uri, + 'name': instance.name, + 'mimeType': instance.mimeType, + 'type': instance.$type, + }; + +FileWithBytes _$FileWithBytesFromJson(Map json) => + FileWithBytes( + bytes: json['bytes'] as String, + name: json['name'] as String?, + mimeType: json['mimeType'] as String?, + $type: json['type'] as String?, + ); + +Map _$FileWithBytesToJson(FileWithBytes instance) => + { + 'bytes': instance.bytes, + 'name': instance.name, + 'mimeType': instance.mimeType, + 'type': instance.$type, + }; diff --git a/packages/a2a_dart/lib/src/core/push_notification.dart b/packages/a2a_dart/lib/src/core/push_notification.dart new file mode 100644 index 000000000..bab49c828 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/push_notification.dart @@ -0,0 +1,72 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'push_notification.freezed.dart'; +part 'push_notification.g.dart'; + +/// Defines the configuration for setting up push notifications for task +/// updates. +@freezed +abstract class PushNotificationConfig with _$PushNotificationConfig { + /// Creates a [PushNotificationConfig]. + const factory PushNotificationConfig({ + /// A unique identifier (e.g. UUID) for the push notification configuration, + /// set by the client to support multiple notification callbacks. + String? id, + + /// The callback URL where the agent should send push notifications. + required String url, + + /// A unique token for this task or session to validate incoming push + /// notifications. + String? token, + + /// Optional authentication details for the agent to use when calling the + /// notification URL. + PushNotificationAuthenticationInfo? authentication, + }) = _PushNotificationConfig; + + /// Creates a [PushNotificationConfig] from a JSON object. + factory PushNotificationConfig.fromJson(Map json) => + _$PushNotificationConfigFromJson(json); +} + +/// Defines authentication details for a push notification endpoint. +@freezed +abstract class PushNotificationAuthenticationInfo + with _$PushNotificationAuthenticationInfo { + /// Creates a [PushNotificationAuthenticationInfo]. + const factory PushNotificationAuthenticationInfo({ + /// A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). + required List schemes, + + /// Optional credentials required by the push notification endpoint. + String? credentials, + }) = _PushNotificationAuthenticationInfo; + + /// Creates a [PushNotificationAuthenticationInfo] from a JSON object. + factory PushNotificationAuthenticationInfo.fromJson( + Map json, + ) => _$PushNotificationAuthenticationInfoFromJson(json); +} + +/// A container associating a push notification configuration with a specific +/// task. +@freezed +abstract class TaskPushNotificationConfig with _$TaskPushNotificationConfig { + /// Creates a [TaskPushNotificationConfig]. + const factory TaskPushNotificationConfig({ + /// The unique identifier (e.g. UUID) of the task. + required String taskId, + + /// The push notification configuration for this task. + required PushNotificationConfig pushNotificationConfig, + }) = _TaskPushNotificationConfig; + + /// Creates a [TaskPushNotificationConfig] from a JSON object. + factory TaskPushNotificationConfig.fromJson(Map json) => + _$TaskPushNotificationConfigFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/push_notification.freezed.dart b/packages/a2a_dart/lib/src/core/push_notification.freezed.dart new file mode 100644 index 000000000..d4728ff93 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/push_notification.freezed.dart @@ -0,0 +1,889 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'push_notification.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$PushNotificationConfig { + +/// A unique identifier (e.g. UUID) for the push notification configuration, +/// set by the client to support multiple notification callbacks. + String? get id;/// The callback URL where the agent should send push notifications. + String get url;/// A unique token for this task or session to validate incoming push +/// notifications. + String? get token;/// Optional authentication details for the agent to use when calling the +/// notification URL. + PushNotificationAuthenticationInfo? get authentication; +/// Create a copy of PushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$PushNotificationConfigCopyWith get copyWith => _$PushNotificationConfigCopyWithImpl(this as PushNotificationConfig, _$identity); + + /// Serializes this PushNotificationConfig to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is PushNotificationConfig&&(identical(other.id, id) || other.id == id)&&(identical(other.url, url) || other.url == url)&&(identical(other.token, token) || other.token == token)&&(identical(other.authentication, authentication) || other.authentication == authentication)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,url,token,authentication); + +@override +String toString() { + return 'PushNotificationConfig(id: $id, url: $url, token: $token, authentication: $authentication)'; +} + + +} + +/// @nodoc +abstract mixin class $PushNotificationConfigCopyWith<$Res> { + factory $PushNotificationConfigCopyWith(PushNotificationConfig value, $Res Function(PushNotificationConfig) _then) = _$PushNotificationConfigCopyWithImpl; +@useResult +$Res call({ + String? id, String url, String? token, PushNotificationAuthenticationInfo? authentication +}); + + +$PushNotificationAuthenticationInfoCopyWith<$Res>? get authentication; + +} +/// @nodoc +class _$PushNotificationConfigCopyWithImpl<$Res> + implements $PushNotificationConfigCopyWith<$Res> { + _$PushNotificationConfigCopyWithImpl(this._self, this._then); + + final PushNotificationConfig _self; + final $Res Function(PushNotificationConfig) _then; + +/// Create a copy of PushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = freezed,Object? url = null,Object? token = freezed,Object? authentication = freezed,}) { + return _then(_self.copyWith( +id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String?,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String,token: freezed == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String?,authentication: freezed == authentication ? _self.authentication : authentication // ignore: cast_nullable_to_non_nullable +as PushNotificationAuthenticationInfo?, + )); +} +/// Create a copy of PushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$PushNotificationAuthenticationInfoCopyWith<$Res>? get authentication { + if (_self.authentication == null) { + return null; + } + + return $PushNotificationAuthenticationInfoCopyWith<$Res>(_self.authentication!, (value) { + return _then(_self.copyWith(authentication: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [PushNotificationConfig]. +extension PushNotificationConfigPatterns on PushNotificationConfig { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _PushNotificationConfig value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _PushNotificationConfig() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _PushNotificationConfig value) $default,){ +final _that = this; +switch (_that) { +case _PushNotificationConfig(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _PushNotificationConfig value)? $default,){ +final _that = this; +switch (_that) { +case _PushNotificationConfig() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String? id, String url, String? token, PushNotificationAuthenticationInfo? authentication)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _PushNotificationConfig() when $default != null: +return $default(_that.id,_that.url,_that.token,_that.authentication);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String? id, String url, String? token, PushNotificationAuthenticationInfo? authentication) $default,) {final _that = this; +switch (_that) { +case _PushNotificationConfig(): +return $default(_that.id,_that.url,_that.token,_that.authentication);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String? id, String url, String? token, PushNotificationAuthenticationInfo? authentication)? $default,) {final _that = this; +switch (_that) { +case _PushNotificationConfig() when $default != null: +return $default(_that.id,_that.url,_that.token,_that.authentication);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _PushNotificationConfig implements PushNotificationConfig { + const _PushNotificationConfig({this.id, required this.url, this.token, this.authentication}); + factory _PushNotificationConfig.fromJson(Map json) => _$PushNotificationConfigFromJson(json); + +/// A unique identifier (e.g. UUID) for the push notification configuration, +/// set by the client to support multiple notification callbacks. +@override final String? id; +/// The callback URL where the agent should send push notifications. +@override final String url; +/// A unique token for this task or session to validate incoming push +/// notifications. +@override final String? token; +/// Optional authentication details for the agent to use when calling the +/// notification URL. +@override final PushNotificationAuthenticationInfo? authentication; + +/// Create a copy of PushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$PushNotificationConfigCopyWith<_PushNotificationConfig> get copyWith => __$PushNotificationConfigCopyWithImpl<_PushNotificationConfig>(this, _$identity); + +@override +Map toJson() { + return _$PushNotificationConfigToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _PushNotificationConfig&&(identical(other.id, id) || other.id == id)&&(identical(other.url, url) || other.url == url)&&(identical(other.token, token) || other.token == token)&&(identical(other.authentication, authentication) || other.authentication == authentication)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,url,token,authentication); + +@override +String toString() { + return 'PushNotificationConfig(id: $id, url: $url, token: $token, authentication: $authentication)'; +} + + +} + +/// @nodoc +abstract mixin class _$PushNotificationConfigCopyWith<$Res> implements $PushNotificationConfigCopyWith<$Res> { + factory _$PushNotificationConfigCopyWith(_PushNotificationConfig value, $Res Function(_PushNotificationConfig) _then) = __$PushNotificationConfigCopyWithImpl; +@override @useResult +$Res call({ + String? id, String url, String? token, PushNotificationAuthenticationInfo? authentication +}); + + +@override $PushNotificationAuthenticationInfoCopyWith<$Res>? get authentication; + +} +/// @nodoc +class __$PushNotificationConfigCopyWithImpl<$Res> + implements _$PushNotificationConfigCopyWith<$Res> { + __$PushNotificationConfigCopyWithImpl(this._self, this._then); + + final _PushNotificationConfig _self; + final $Res Function(_PushNotificationConfig) _then; + +/// Create a copy of PushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = freezed,Object? url = null,Object? token = freezed,Object? authentication = freezed,}) { + return _then(_PushNotificationConfig( +id: freezed == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String?,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable +as String,token: freezed == token ? _self.token : token // ignore: cast_nullable_to_non_nullable +as String?,authentication: freezed == authentication ? _self.authentication : authentication // ignore: cast_nullable_to_non_nullable +as PushNotificationAuthenticationInfo?, + )); +} + +/// Create a copy of PushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$PushNotificationAuthenticationInfoCopyWith<$Res>? get authentication { + if (_self.authentication == null) { + return null; + } + + return $PushNotificationAuthenticationInfoCopyWith<$Res>(_self.authentication!, (value) { + return _then(_self.copyWith(authentication: value)); + }); +} +} + + +/// @nodoc +mixin _$PushNotificationAuthenticationInfo { + +/// A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). + List get schemes;/// Optional credentials required by the push notification endpoint. + String? get credentials; +/// Create a copy of PushNotificationAuthenticationInfo +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$PushNotificationAuthenticationInfoCopyWith get copyWith => _$PushNotificationAuthenticationInfoCopyWithImpl(this as PushNotificationAuthenticationInfo, _$identity); + + /// Serializes this PushNotificationAuthenticationInfo to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is PushNotificationAuthenticationInfo&&const DeepCollectionEquality().equals(other.schemes, schemes)&&(identical(other.credentials, credentials) || other.credentials == credentials)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(schemes),credentials); + +@override +String toString() { + return 'PushNotificationAuthenticationInfo(schemes: $schemes, credentials: $credentials)'; +} + + +} + +/// @nodoc +abstract mixin class $PushNotificationAuthenticationInfoCopyWith<$Res> { + factory $PushNotificationAuthenticationInfoCopyWith(PushNotificationAuthenticationInfo value, $Res Function(PushNotificationAuthenticationInfo) _then) = _$PushNotificationAuthenticationInfoCopyWithImpl; +@useResult +$Res call({ + List schemes, String? credentials +}); + + + + +} +/// @nodoc +class _$PushNotificationAuthenticationInfoCopyWithImpl<$Res> + implements $PushNotificationAuthenticationInfoCopyWith<$Res> { + _$PushNotificationAuthenticationInfoCopyWithImpl(this._self, this._then); + + final PushNotificationAuthenticationInfo _self; + final $Res Function(PushNotificationAuthenticationInfo) _then; + +/// Create a copy of PushNotificationAuthenticationInfo +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? schemes = null,Object? credentials = freezed,}) { + return _then(_self.copyWith( +schemes: null == schemes ? _self.schemes : schemes // ignore: cast_nullable_to_non_nullable +as List,credentials: freezed == credentials ? _self.credentials : credentials // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [PushNotificationAuthenticationInfo]. +extension PushNotificationAuthenticationInfoPatterns on PushNotificationAuthenticationInfo { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _PushNotificationAuthenticationInfo value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _PushNotificationAuthenticationInfo() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _PushNotificationAuthenticationInfo value) $default,){ +final _that = this; +switch (_that) { +case _PushNotificationAuthenticationInfo(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _PushNotificationAuthenticationInfo value)? $default,){ +final _that = this; +switch (_that) { +case _PushNotificationAuthenticationInfo() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List schemes, String? credentials)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _PushNotificationAuthenticationInfo() when $default != null: +return $default(_that.schemes,_that.credentials);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List schemes, String? credentials) $default,) {final _that = this; +switch (_that) { +case _PushNotificationAuthenticationInfo(): +return $default(_that.schemes,_that.credentials);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List schemes, String? credentials)? $default,) {final _that = this; +switch (_that) { +case _PushNotificationAuthenticationInfo() when $default != null: +return $default(_that.schemes,_that.credentials);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _PushNotificationAuthenticationInfo implements PushNotificationAuthenticationInfo { + const _PushNotificationAuthenticationInfo({required final List schemes, this.credentials}): _schemes = schemes; + factory _PushNotificationAuthenticationInfo.fromJson(Map json) => _$PushNotificationAuthenticationInfoFromJson(json); + +/// A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). + final List _schemes; +/// A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). +@override List get schemes { + if (_schemes is EqualUnmodifiableListView) return _schemes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_schemes); +} + +/// Optional credentials required by the push notification endpoint. +@override final String? credentials; + +/// Create a copy of PushNotificationAuthenticationInfo +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$PushNotificationAuthenticationInfoCopyWith<_PushNotificationAuthenticationInfo> get copyWith => __$PushNotificationAuthenticationInfoCopyWithImpl<_PushNotificationAuthenticationInfo>(this, _$identity); + +@override +Map toJson() { + return _$PushNotificationAuthenticationInfoToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _PushNotificationAuthenticationInfo&&const DeepCollectionEquality().equals(other._schemes, _schemes)&&(identical(other.credentials, credentials) || other.credentials == credentials)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_schemes),credentials); + +@override +String toString() { + return 'PushNotificationAuthenticationInfo(schemes: $schemes, credentials: $credentials)'; +} + + +} + +/// @nodoc +abstract mixin class _$PushNotificationAuthenticationInfoCopyWith<$Res> implements $PushNotificationAuthenticationInfoCopyWith<$Res> { + factory _$PushNotificationAuthenticationInfoCopyWith(_PushNotificationAuthenticationInfo value, $Res Function(_PushNotificationAuthenticationInfo) _then) = __$PushNotificationAuthenticationInfoCopyWithImpl; +@override @useResult +$Res call({ + List schemes, String? credentials +}); + + + + +} +/// @nodoc +class __$PushNotificationAuthenticationInfoCopyWithImpl<$Res> + implements _$PushNotificationAuthenticationInfoCopyWith<$Res> { + __$PushNotificationAuthenticationInfoCopyWithImpl(this._self, this._then); + + final _PushNotificationAuthenticationInfo _self; + final $Res Function(_PushNotificationAuthenticationInfo) _then; + +/// Create a copy of PushNotificationAuthenticationInfo +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? schemes = null,Object? credentials = freezed,}) { + return _then(_PushNotificationAuthenticationInfo( +schemes: null == schemes ? _self._schemes : schemes // ignore: cast_nullable_to_non_nullable +as List,credentials: freezed == credentials ? _self.credentials : credentials // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + + +/// @nodoc +mixin _$TaskPushNotificationConfig { + +/// The unique identifier (e.g. UUID) of the task. + String get taskId;/// The push notification configuration for this task. + PushNotificationConfig get pushNotificationConfig; +/// Create a copy of TaskPushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TaskPushNotificationConfigCopyWith get copyWith => _$TaskPushNotificationConfigCopyWithImpl(this as TaskPushNotificationConfig, _$identity); + + /// Serializes this TaskPushNotificationConfig to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TaskPushNotificationConfig&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.pushNotificationConfig, pushNotificationConfig) || other.pushNotificationConfig == pushNotificationConfig)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,taskId,pushNotificationConfig); + +@override +String toString() { + return 'TaskPushNotificationConfig(taskId: $taskId, pushNotificationConfig: $pushNotificationConfig)'; +} + + +} + +/// @nodoc +abstract mixin class $TaskPushNotificationConfigCopyWith<$Res> { + factory $TaskPushNotificationConfigCopyWith(TaskPushNotificationConfig value, $Res Function(TaskPushNotificationConfig) _then) = _$TaskPushNotificationConfigCopyWithImpl; +@useResult +$Res call({ + String taskId, PushNotificationConfig pushNotificationConfig +}); + + +$PushNotificationConfigCopyWith<$Res> get pushNotificationConfig; + +} +/// @nodoc +class _$TaskPushNotificationConfigCopyWithImpl<$Res> + implements $TaskPushNotificationConfigCopyWith<$Res> { + _$TaskPushNotificationConfigCopyWithImpl(this._self, this._then); + + final TaskPushNotificationConfig _self; + final $Res Function(TaskPushNotificationConfig) _then; + +/// Create a copy of TaskPushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? taskId = null,Object? pushNotificationConfig = null,}) { + return _then(_self.copyWith( +taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,pushNotificationConfig: null == pushNotificationConfig ? _self.pushNotificationConfig : pushNotificationConfig // ignore: cast_nullable_to_non_nullable +as PushNotificationConfig, + )); +} +/// Create a copy of TaskPushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$PushNotificationConfigCopyWith<$Res> get pushNotificationConfig { + + return $PushNotificationConfigCopyWith<$Res>(_self.pushNotificationConfig, (value) { + return _then(_self.copyWith(pushNotificationConfig: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [TaskPushNotificationConfig]. +extension TaskPushNotificationConfigPatterns on TaskPushNotificationConfig { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _TaskPushNotificationConfig value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _TaskPushNotificationConfig() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _TaskPushNotificationConfig value) $default,){ +final _that = this; +switch (_that) { +case _TaskPushNotificationConfig(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _TaskPushNotificationConfig value)? $default,){ +final _that = this; +switch (_that) { +case _TaskPushNotificationConfig() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String taskId, PushNotificationConfig pushNotificationConfig)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _TaskPushNotificationConfig() when $default != null: +return $default(_that.taskId,_that.pushNotificationConfig);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String taskId, PushNotificationConfig pushNotificationConfig) $default,) {final _that = this; +switch (_that) { +case _TaskPushNotificationConfig(): +return $default(_that.taskId,_that.pushNotificationConfig);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String taskId, PushNotificationConfig pushNotificationConfig)? $default,) {final _that = this; +switch (_that) { +case _TaskPushNotificationConfig() when $default != null: +return $default(_that.taskId,_that.pushNotificationConfig);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _TaskPushNotificationConfig implements TaskPushNotificationConfig { + const _TaskPushNotificationConfig({required this.taskId, required this.pushNotificationConfig}); + factory _TaskPushNotificationConfig.fromJson(Map json) => _$TaskPushNotificationConfigFromJson(json); + +/// The unique identifier (e.g. UUID) of the task. +@override final String taskId; +/// The push notification configuration for this task. +@override final PushNotificationConfig pushNotificationConfig; + +/// Create a copy of TaskPushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$TaskPushNotificationConfigCopyWith<_TaskPushNotificationConfig> get copyWith => __$TaskPushNotificationConfigCopyWithImpl<_TaskPushNotificationConfig>(this, _$identity); + +@override +Map toJson() { + return _$TaskPushNotificationConfigToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _TaskPushNotificationConfig&&(identical(other.taskId, taskId) || other.taskId == taskId)&&(identical(other.pushNotificationConfig, pushNotificationConfig) || other.pushNotificationConfig == pushNotificationConfig)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,taskId,pushNotificationConfig); + +@override +String toString() { + return 'TaskPushNotificationConfig(taskId: $taskId, pushNotificationConfig: $pushNotificationConfig)'; +} + + +} + +/// @nodoc +abstract mixin class _$TaskPushNotificationConfigCopyWith<$Res> implements $TaskPushNotificationConfigCopyWith<$Res> { + factory _$TaskPushNotificationConfigCopyWith(_TaskPushNotificationConfig value, $Res Function(_TaskPushNotificationConfig) _then) = __$TaskPushNotificationConfigCopyWithImpl; +@override @useResult +$Res call({ + String taskId, PushNotificationConfig pushNotificationConfig +}); + + +@override $PushNotificationConfigCopyWith<$Res> get pushNotificationConfig; + +} +/// @nodoc +class __$TaskPushNotificationConfigCopyWithImpl<$Res> + implements _$TaskPushNotificationConfigCopyWith<$Res> { + __$TaskPushNotificationConfigCopyWithImpl(this._self, this._then); + + final _TaskPushNotificationConfig _self; + final $Res Function(_TaskPushNotificationConfig) _then; + +/// Create a copy of TaskPushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? taskId = null,Object? pushNotificationConfig = null,}) { + return _then(_TaskPushNotificationConfig( +taskId: null == taskId ? _self.taskId : taskId // ignore: cast_nullable_to_non_nullable +as String,pushNotificationConfig: null == pushNotificationConfig ? _self.pushNotificationConfig : pushNotificationConfig // ignore: cast_nullable_to_non_nullable +as PushNotificationConfig, + )); +} + +/// Create a copy of TaskPushNotificationConfig +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$PushNotificationConfigCopyWith<$Res> get pushNotificationConfig { + + return $PushNotificationConfigCopyWith<$Res>(_self.pushNotificationConfig, (value) { + return _then(_self.copyWith(pushNotificationConfig: value)); + }); +} +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/push_notification.g.dart b/packages/a2a_dart/lib/src/core/push_notification.g.dart new file mode 100644 index 000000000..5cd22a20c --- /dev/null +++ b/packages/a2a_dart/lib/src/core/push_notification.g.dart @@ -0,0 +1,61 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'push_notification.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_PushNotificationConfig _$PushNotificationConfigFromJson( + Map json, +) => _PushNotificationConfig( + id: json['id'] as String?, + url: json['url'] as String, + token: json['token'] as String?, + authentication: json['authentication'] == null + ? null + : PushNotificationAuthenticationInfo.fromJson( + json['authentication'] as Map, + ), +); + +Map _$PushNotificationConfigToJson( + _PushNotificationConfig instance, +) => { + 'id': instance.id, + 'url': instance.url, + 'token': instance.token, + 'authentication': instance.authentication?.toJson(), +}; + +_PushNotificationAuthenticationInfo +_$PushNotificationAuthenticationInfoFromJson(Map json) => + _PushNotificationAuthenticationInfo( + schemes: (json['schemes'] as List) + .map((e) => e as String) + .toList(), + credentials: json['credentials'] as String?, + ); + +Map _$PushNotificationAuthenticationInfoToJson( + _PushNotificationAuthenticationInfo instance, +) => { + 'schemes': instance.schemes, + 'credentials': instance.credentials, +}; + +_TaskPushNotificationConfig _$TaskPushNotificationConfigFromJson( + Map json, +) => _TaskPushNotificationConfig( + taskId: json['taskId'] as String, + pushNotificationConfig: PushNotificationConfig.fromJson( + json['pushNotificationConfig'] as Map, + ), +); + +Map _$TaskPushNotificationConfigToJson( + _TaskPushNotificationConfig instance, +) => { + 'taskId': instance.taskId, + 'pushNotificationConfig': instance.pushNotificationConfig.toJson(), +}; diff --git a/packages/a2a_dart/lib/src/core/security_scheme.dart b/packages/a2a_dart/lib/src/core/security_scheme.dart new file mode 100644 index 000000000..834ce911d --- /dev/null +++ b/packages/a2a_dart/lib/src/core/security_scheme.dart @@ -0,0 +1,149 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'security_scheme.freezed.dart'; +part 'security_scheme.g.dart'; + +// ignore_for_file: invalid_annotation_target + +/// Defines a security scheme used to protect an agent's API endpoints. +/// +/// This class is a Dart representation of the OpenAPI 3.0 Security Scheme +/// Object. It's a discriminated union based on the `type` field, allowing for +/// various authentication and authorization mechanisms. +@Freezed(unionKey: 'type') +abstract class SecurityScheme with _$SecurityScheme { + /// Represents an API key-based security scheme. + const factory SecurityScheme.apiKey({ + /// The type discriminator, always 'apiKey'. + @Default('apiKey') String type, + + /// An optional description of the API key security scheme. + String? description, + + /// The name of the header, query, or cookie parameter used to transmit + /// the API key. + required String name, + + /// Specifies the location of the API key. + /// + /// Valid values are "query", "header", or "cookie". + @JsonKey(name: 'in') required String in_, + }) = APIKeySecurityScheme; + + /// Represents an HTTP authentication scheme (e.g., Basic, Bearer). + const factory SecurityScheme.http({ + /// The type discriminator, always 'http'. + @Default('http') String type, + + /// An optional description of the HTTP security scheme. + String? description, + + /// The name of the HTTP Authorization scheme, e.g., "Bearer", "Basic". + /// + /// Values should be registered in the IANA "Hypertext Transfer Protocol + /// (HTTP) Authentication Scheme Registry". + required String scheme, + + /// An optional hint about the format of the bearer token (e.g., "JWT"). + /// + /// Only relevant when `scheme` is "Bearer". + String? bearerFormat, + }) = HttpAuthSecurityScheme; + + /// Represents an OAuth 2.0 security scheme. + const factory SecurityScheme.oauth2({ + /// The type discriminator, always 'oauth2'. + @Default('oauth2') String type, + + /// An optional description of the OAuth 2.0 security scheme. + String? description, + + /// Configuration details for the supported OAuth 2.0 flows. + required OAuthFlows flows, + }) = OAuth2SecurityScheme; + + /// Represents an OpenID Connect security scheme. + const factory SecurityScheme.openIdConnect({ + /// The type discriminator, always 'openIdConnect'. + @Default('openIdConnect') String type, + + /// An optional description of the OpenID Connect security scheme. + String? description, + + /// The OpenID Connect Discovery URL (e.g., ending in `.well-known/openid-configuration`). + required String openIdConnectUrl, + }) = OpenIdConnectSecurityScheme; + + /// Represents a mutual TLS authentication scheme. + const factory SecurityScheme.mutualTls({ + /// The type discriminator, always 'mutualTls'. + @Default('mutualTls') String type, + + /// An optional description of the mutual TLS security scheme. + String? description, + }) = MutualTlsSecurityScheme; + + /// Deserializes a [SecurityScheme] instance from a JSON object. + factory SecurityScheme.fromJson(Map json) => + _$SecuritySchemeFromJson(json); +} + +/// Container for the OAuth 2.0 flows supported by a [SecurityScheme.oauth2]. +/// +/// Each property represents a different OAuth 2.0 grant type. +@freezed +abstract class OAuthFlows with _$OAuthFlows { + /// Creates an [OAuthFlows] instance. + const factory OAuthFlows({ + /// Configuration for the Implicit Grant flow. + OAuthFlow? implicit, + + /// Configuration for the Resource Owner Password Credentials Grant flow. + OAuthFlow? password, + + /// Configuration for the Client Credentials Grant flow. + OAuthFlow? clientCredentials, + + /// Configuration for the Authorization Code Grant flow. + OAuthFlow? authorizationCode, + }) = _OAuthFlows; + + /// Deserializes an [OAuthFlows] instance from a JSON object. + factory OAuthFlows.fromJson(Map json) => + _$OAuthFlowsFromJson(json); +} + +/// Configuration details for a single OAuth 2.0 flow. +@freezed +abstract class OAuthFlow with _$OAuthFlow { + /// Creates an [OAuthFlow] instance. + const factory OAuthFlow({ + /// The Authorization URL for this flow. + /// + /// Required for `implicit` and `authorizationCode` flows. + String? authorizationUrl, + + /// The Token URL for this flow. + /// + /// Required for `password`, `clientCredentials`, and `authorizationCode` + /// flows. + String? tokenUrl, + + /// The Refresh URL to obtain a new access token. + String? refreshUrl, + + /// A map of available scopes for this flow. + /// + /// The keys are scope names, and the values are human-readable + /// descriptions. + required Map scopes, + }) = _OAuthFlow; + + /// Deserializes an [OAuthFlow] instance from a JSON object. + factory OAuthFlow.fromJson(Map json) => + _$OAuthFlowFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/security_scheme.freezed.dart b/packages/a2a_dart/lib/src/core/security_scheme.freezed.dart new file mode 100644 index 000000000..54d3d830b --- /dev/null +++ b/packages/a2a_dart/lib/src/core/security_scheme.freezed.dart @@ -0,0 +1,1352 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'security_scheme.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +SecurityScheme _$SecuritySchemeFromJson( + Map json +) { + switch (json['type']) { + case 'apiKey': + return APIKeySecurityScheme.fromJson( + json + ); + case 'http': + return HttpAuthSecurityScheme.fromJson( + json + ); + case 'oauth2': + return OAuth2SecurityScheme.fromJson( + json + ); + case 'openIdConnect': + return OpenIdConnectSecurityScheme.fromJson( + json + ); + case 'mutualTls': + return MutualTlsSecurityScheme.fromJson( + json + ); + + default: + throw CheckedFromJsonException( + json, + 'type', + 'SecurityScheme', + 'Invalid union type "${json['type']}"!' +); + } + +} + +/// @nodoc +mixin _$SecurityScheme { + +/// The type discriminator, always 'apiKey'. + String get type;/// An optional description of the API key security scheme. + String? get description; +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$SecuritySchemeCopyWith get copyWith => _$SecuritySchemeCopyWithImpl(this as SecurityScheme, _$identity); + + /// Serializes this SecurityScheme to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is SecurityScheme&&(identical(other.type, type) || other.type == type)&&(identical(other.description, description) || other.description == description)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,type,description); + +@override +String toString() { + return 'SecurityScheme(type: $type, description: $description)'; +} + + +} + +/// @nodoc +abstract mixin class $SecuritySchemeCopyWith<$Res> { + factory $SecuritySchemeCopyWith(SecurityScheme value, $Res Function(SecurityScheme) _then) = _$SecuritySchemeCopyWithImpl; +@useResult +$Res call({ + String type, String? description +}); + + + + +} +/// @nodoc +class _$SecuritySchemeCopyWithImpl<$Res> + implements $SecuritySchemeCopyWith<$Res> { + _$SecuritySchemeCopyWithImpl(this._self, this._then); + + final SecurityScheme _self; + final $Res Function(SecurityScheme) _then; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? description = freezed,}) { + return _then(_self.copyWith( +type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [SecurityScheme]. +extension SecuritySchemePatterns on SecurityScheme { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( APIKeySecurityScheme value)? apiKey,TResult Function( HttpAuthSecurityScheme value)? http,TResult Function( OAuth2SecurityScheme value)? oauth2,TResult Function( OpenIdConnectSecurityScheme value)? openIdConnect,TResult Function( MutualTlsSecurityScheme value)? mutualTls,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case APIKeySecurityScheme() when apiKey != null: +return apiKey(_that);case HttpAuthSecurityScheme() when http != null: +return http(_that);case OAuth2SecurityScheme() when oauth2 != null: +return oauth2(_that);case OpenIdConnectSecurityScheme() when openIdConnect != null: +return openIdConnect(_that);case MutualTlsSecurityScheme() when mutualTls != null: +return mutualTls(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( APIKeySecurityScheme value) apiKey,required TResult Function( HttpAuthSecurityScheme value) http,required TResult Function( OAuth2SecurityScheme value) oauth2,required TResult Function( OpenIdConnectSecurityScheme value) openIdConnect,required TResult Function( MutualTlsSecurityScheme value) mutualTls,}){ +final _that = this; +switch (_that) { +case APIKeySecurityScheme(): +return apiKey(_that);case HttpAuthSecurityScheme(): +return http(_that);case OAuth2SecurityScheme(): +return oauth2(_that);case OpenIdConnectSecurityScheme(): +return openIdConnect(_that);case MutualTlsSecurityScheme(): +return mutualTls(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( APIKeySecurityScheme value)? apiKey,TResult? Function( HttpAuthSecurityScheme value)? http,TResult? Function( OAuth2SecurityScheme value)? oauth2,TResult? Function( OpenIdConnectSecurityScheme value)? openIdConnect,TResult? Function( MutualTlsSecurityScheme value)? mutualTls,}){ +final _that = this; +switch (_that) { +case APIKeySecurityScheme() when apiKey != null: +return apiKey(_that);case HttpAuthSecurityScheme() when http != null: +return http(_that);case OAuth2SecurityScheme() when oauth2 != null: +return oauth2(_that);case OpenIdConnectSecurityScheme() when openIdConnect != null: +return openIdConnect(_that);case MutualTlsSecurityScheme() when mutualTls != null: +return mutualTls(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( String type, String? description, String name, @JsonKey(name: 'in') String in_)? apiKey,TResult Function( String type, String? description, String scheme, String? bearerFormat)? http,TResult Function( String type, String? description, OAuthFlows flows)? oauth2,TResult Function( String type, String? description, String openIdConnectUrl)? openIdConnect,TResult Function( String type, String? description)? mutualTls,required TResult orElse(),}) {final _that = this; +switch (_that) { +case APIKeySecurityScheme() when apiKey != null: +return apiKey(_that.type,_that.description,_that.name,_that.in_);case HttpAuthSecurityScheme() when http != null: +return http(_that.type,_that.description,_that.scheme,_that.bearerFormat);case OAuth2SecurityScheme() when oauth2 != null: +return oauth2(_that.type,_that.description,_that.flows);case OpenIdConnectSecurityScheme() when openIdConnect != null: +return openIdConnect(_that.type,_that.description,_that.openIdConnectUrl);case MutualTlsSecurityScheme() when mutualTls != null: +return mutualTls(_that.type,_that.description);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( String type, String? description, String name, @JsonKey(name: 'in') String in_) apiKey,required TResult Function( String type, String? description, String scheme, String? bearerFormat) http,required TResult Function( String type, String? description, OAuthFlows flows) oauth2,required TResult Function( String type, String? description, String openIdConnectUrl) openIdConnect,required TResult Function( String type, String? description) mutualTls,}) {final _that = this; +switch (_that) { +case APIKeySecurityScheme(): +return apiKey(_that.type,_that.description,_that.name,_that.in_);case HttpAuthSecurityScheme(): +return http(_that.type,_that.description,_that.scheme,_that.bearerFormat);case OAuth2SecurityScheme(): +return oauth2(_that.type,_that.description,_that.flows);case OpenIdConnectSecurityScheme(): +return openIdConnect(_that.type,_that.description,_that.openIdConnectUrl);case MutualTlsSecurityScheme(): +return mutualTls(_that.type,_that.description);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( String type, String? description, String name, @JsonKey(name: 'in') String in_)? apiKey,TResult? Function( String type, String? description, String scheme, String? bearerFormat)? http,TResult? Function( String type, String? description, OAuthFlows flows)? oauth2,TResult? Function( String type, String? description, String openIdConnectUrl)? openIdConnect,TResult? Function( String type, String? description)? mutualTls,}) {final _that = this; +switch (_that) { +case APIKeySecurityScheme() when apiKey != null: +return apiKey(_that.type,_that.description,_that.name,_that.in_);case HttpAuthSecurityScheme() when http != null: +return http(_that.type,_that.description,_that.scheme,_that.bearerFormat);case OAuth2SecurityScheme() when oauth2 != null: +return oauth2(_that.type,_that.description,_that.flows);case OpenIdConnectSecurityScheme() when openIdConnect != null: +return openIdConnect(_that.type,_that.description,_that.openIdConnectUrl);case MutualTlsSecurityScheme() when mutualTls != null: +return mutualTls(_that.type,_that.description);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class APIKeySecurityScheme implements SecurityScheme { + const APIKeySecurityScheme({this.type = 'apiKey', this.description, required this.name, @JsonKey(name: 'in') required this.in_}); + factory APIKeySecurityScheme.fromJson(Map json) => _$APIKeySecuritySchemeFromJson(json); + +/// The type discriminator, always 'apiKey'. +@override@JsonKey() final String type; +/// An optional description of the API key security scheme. +@override final String? description; +/// The name of the header, query, or cookie parameter used to transmit +/// the API key. + final String name; +/// Specifies the location of the API key. +/// +/// Valid values are "query", "header", or "cookie". +@JsonKey(name: 'in') final String in_; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$APIKeySecuritySchemeCopyWith get copyWith => _$APIKeySecuritySchemeCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$APIKeySecuritySchemeToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is APIKeySecurityScheme&&(identical(other.type, type) || other.type == type)&&(identical(other.description, description) || other.description == description)&&(identical(other.name, name) || other.name == name)&&(identical(other.in_, in_) || other.in_ == in_)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,type,description,name,in_); + +@override +String toString() { + return 'SecurityScheme.apiKey(type: $type, description: $description, name: $name, in_: $in_)'; +} + + +} + +/// @nodoc +abstract mixin class $APIKeySecuritySchemeCopyWith<$Res> implements $SecuritySchemeCopyWith<$Res> { + factory $APIKeySecuritySchemeCopyWith(APIKeySecurityScheme value, $Res Function(APIKeySecurityScheme) _then) = _$APIKeySecuritySchemeCopyWithImpl; +@override @useResult +$Res call({ + String type, String? description, String name,@JsonKey(name: 'in') String in_ +}); + + + + +} +/// @nodoc +class _$APIKeySecuritySchemeCopyWithImpl<$Res> + implements $APIKeySecuritySchemeCopyWith<$Res> { + _$APIKeySecuritySchemeCopyWithImpl(this._self, this._then); + + final APIKeySecurityScheme _self; + final $Res Function(APIKeySecurityScheme) _then; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? description = freezed,Object? name = null,Object? in_ = null,}) { + return _then(APIKeySecurityScheme( +type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String,in_: null == in_ ? _self.in_ : in_ // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class HttpAuthSecurityScheme implements SecurityScheme { + const HttpAuthSecurityScheme({this.type = 'http', this.description, required this.scheme, this.bearerFormat}); + factory HttpAuthSecurityScheme.fromJson(Map json) => _$HttpAuthSecuritySchemeFromJson(json); + +/// The type discriminator, always 'http'. +@override@JsonKey() final String type; +/// An optional description of the HTTP security scheme. +@override final String? description; +/// The name of the HTTP Authorization scheme, e.g., "Bearer", "Basic". +/// +/// Values should be registered in the IANA "Hypertext Transfer Protocol +/// (HTTP) Authentication Scheme Registry". + final String scheme; +/// An optional hint about the format of the bearer token (e.g., "JWT"). +/// +/// Only relevant when `scheme` is "Bearer". + final String? bearerFormat; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$HttpAuthSecuritySchemeCopyWith get copyWith => _$HttpAuthSecuritySchemeCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$HttpAuthSecuritySchemeToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is HttpAuthSecurityScheme&&(identical(other.type, type) || other.type == type)&&(identical(other.description, description) || other.description == description)&&(identical(other.scheme, scheme) || other.scheme == scheme)&&(identical(other.bearerFormat, bearerFormat) || other.bearerFormat == bearerFormat)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,type,description,scheme,bearerFormat); + +@override +String toString() { + return 'SecurityScheme.http(type: $type, description: $description, scheme: $scheme, bearerFormat: $bearerFormat)'; +} + + +} + +/// @nodoc +abstract mixin class $HttpAuthSecuritySchemeCopyWith<$Res> implements $SecuritySchemeCopyWith<$Res> { + factory $HttpAuthSecuritySchemeCopyWith(HttpAuthSecurityScheme value, $Res Function(HttpAuthSecurityScheme) _then) = _$HttpAuthSecuritySchemeCopyWithImpl; +@override @useResult +$Res call({ + String type, String? description, String scheme, String? bearerFormat +}); + + + + +} +/// @nodoc +class _$HttpAuthSecuritySchemeCopyWithImpl<$Res> + implements $HttpAuthSecuritySchemeCopyWith<$Res> { + _$HttpAuthSecuritySchemeCopyWithImpl(this._self, this._then); + + final HttpAuthSecurityScheme _self; + final $Res Function(HttpAuthSecurityScheme) _then; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? description = freezed,Object? scheme = null,Object? bearerFormat = freezed,}) { + return _then(HttpAuthSecurityScheme( +type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,scheme: null == scheme ? _self.scheme : scheme // ignore: cast_nullable_to_non_nullable +as String,bearerFormat: freezed == bearerFormat ? _self.bearerFormat : bearerFormat // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class OAuth2SecurityScheme implements SecurityScheme { + const OAuth2SecurityScheme({this.type = 'oauth2', this.description, required this.flows}); + factory OAuth2SecurityScheme.fromJson(Map json) => _$OAuth2SecuritySchemeFromJson(json); + +/// The type discriminator, always 'oauth2'. +@override@JsonKey() final String type; +/// An optional description of the OAuth 2.0 security scheme. +@override final String? description; +/// Configuration details for the supported OAuth 2.0 flows. + final OAuthFlows flows; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$OAuth2SecuritySchemeCopyWith get copyWith => _$OAuth2SecuritySchemeCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$OAuth2SecuritySchemeToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is OAuth2SecurityScheme&&(identical(other.type, type) || other.type == type)&&(identical(other.description, description) || other.description == description)&&(identical(other.flows, flows) || other.flows == flows)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,type,description,flows); + +@override +String toString() { + return 'SecurityScheme.oauth2(type: $type, description: $description, flows: $flows)'; +} + + +} + +/// @nodoc +abstract mixin class $OAuth2SecuritySchemeCopyWith<$Res> implements $SecuritySchemeCopyWith<$Res> { + factory $OAuth2SecuritySchemeCopyWith(OAuth2SecurityScheme value, $Res Function(OAuth2SecurityScheme) _then) = _$OAuth2SecuritySchemeCopyWithImpl; +@override @useResult +$Res call({ + String type, String? description, OAuthFlows flows +}); + + +$OAuthFlowsCopyWith<$Res> get flows; + +} +/// @nodoc +class _$OAuth2SecuritySchemeCopyWithImpl<$Res> + implements $OAuth2SecuritySchemeCopyWith<$Res> { + _$OAuth2SecuritySchemeCopyWithImpl(this._self, this._then); + + final OAuth2SecurityScheme _self; + final $Res Function(OAuth2SecurityScheme) _then; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? description = freezed,Object? flows = null,}) { + return _then(OAuth2SecurityScheme( +type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,flows: null == flows ? _self.flows : flows // ignore: cast_nullable_to_non_nullable +as OAuthFlows, + )); +} + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowsCopyWith<$Res> get flows { + + return $OAuthFlowsCopyWith<$Res>(_self.flows, (value) { + return _then(_self.copyWith(flows: value)); + }); +} +} + +/// @nodoc +@JsonSerializable() + +class OpenIdConnectSecurityScheme implements SecurityScheme { + const OpenIdConnectSecurityScheme({this.type = 'openIdConnect', this.description, required this.openIdConnectUrl}); + factory OpenIdConnectSecurityScheme.fromJson(Map json) => _$OpenIdConnectSecuritySchemeFromJson(json); + +/// The type discriminator, always 'openIdConnect'. +@override@JsonKey() final String type; +/// An optional description of the OpenID Connect security scheme. +@override final String? description; +/// The OpenID Connect Discovery URL (e.g., ending in `.well-known/openid-configuration`). + final String openIdConnectUrl; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$OpenIdConnectSecuritySchemeCopyWith get copyWith => _$OpenIdConnectSecuritySchemeCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$OpenIdConnectSecuritySchemeToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is OpenIdConnectSecurityScheme&&(identical(other.type, type) || other.type == type)&&(identical(other.description, description) || other.description == description)&&(identical(other.openIdConnectUrl, openIdConnectUrl) || other.openIdConnectUrl == openIdConnectUrl)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,type,description,openIdConnectUrl); + +@override +String toString() { + return 'SecurityScheme.openIdConnect(type: $type, description: $description, openIdConnectUrl: $openIdConnectUrl)'; +} + + +} + +/// @nodoc +abstract mixin class $OpenIdConnectSecuritySchemeCopyWith<$Res> implements $SecuritySchemeCopyWith<$Res> { + factory $OpenIdConnectSecuritySchemeCopyWith(OpenIdConnectSecurityScheme value, $Res Function(OpenIdConnectSecurityScheme) _then) = _$OpenIdConnectSecuritySchemeCopyWithImpl; +@override @useResult +$Res call({ + String type, String? description, String openIdConnectUrl +}); + + + + +} +/// @nodoc +class _$OpenIdConnectSecuritySchemeCopyWithImpl<$Res> + implements $OpenIdConnectSecuritySchemeCopyWith<$Res> { + _$OpenIdConnectSecuritySchemeCopyWithImpl(this._self, this._then); + + final OpenIdConnectSecurityScheme _self; + final $Res Function(OpenIdConnectSecurityScheme) _then; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? description = freezed,Object? openIdConnectUrl = null,}) { + return _then(OpenIdConnectSecurityScheme( +type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,openIdConnectUrl: null == openIdConnectUrl ? _self.openIdConnectUrl : openIdConnectUrl // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +/// @nodoc +@JsonSerializable() + +class MutualTlsSecurityScheme implements SecurityScheme { + const MutualTlsSecurityScheme({this.type = 'mutualTls', this.description}); + factory MutualTlsSecurityScheme.fromJson(Map json) => _$MutualTlsSecuritySchemeFromJson(json); + +/// The type discriminator, always 'mutualTls'. +@override@JsonKey() final String type; +/// An optional description of the mutual TLS security scheme. +@override final String? description; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$MutualTlsSecuritySchemeCopyWith get copyWith => _$MutualTlsSecuritySchemeCopyWithImpl(this, _$identity); + +@override +Map toJson() { + return _$MutualTlsSecuritySchemeToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is MutualTlsSecurityScheme&&(identical(other.type, type) || other.type == type)&&(identical(other.description, description) || other.description == description)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,type,description); + +@override +String toString() { + return 'SecurityScheme.mutualTls(type: $type, description: $description)'; +} + + +} + +/// @nodoc +abstract mixin class $MutualTlsSecuritySchemeCopyWith<$Res> implements $SecuritySchemeCopyWith<$Res> { + factory $MutualTlsSecuritySchemeCopyWith(MutualTlsSecurityScheme value, $Res Function(MutualTlsSecurityScheme) _then) = _$MutualTlsSecuritySchemeCopyWithImpl; +@override @useResult +$Res call({ + String type, String? description +}); + + + + +} +/// @nodoc +class _$MutualTlsSecuritySchemeCopyWithImpl<$Res> + implements $MutualTlsSecuritySchemeCopyWith<$Res> { + _$MutualTlsSecuritySchemeCopyWithImpl(this._self, this._then); + + final MutualTlsSecurityScheme _self; + final $Res Function(MutualTlsSecurityScheme) _then; + +/// Create a copy of SecurityScheme +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? description = freezed,}) { + return _then(MutualTlsSecurityScheme( +type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable +as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + + +/// @nodoc +mixin _$OAuthFlows { + +/// Configuration for the Implicit Grant flow. + OAuthFlow? get implicit;/// Configuration for the Resource Owner Password Credentials Grant flow. + OAuthFlow? get password;/// Configuration for the Client Credentials Grant flow. + OAuthFlow? get clientCredentials;/// Configuration for the Authorization Code Grant flow. + OAuthFlow? get authorizationCode; +/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$OAuthFlowsCopyWith get copyWith => _$OAuthFlowsCopyWithImpl(this as OAuthFlows, _$identity); + + /// Serializes this OAuthFlows to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is OAuthFlows&&(identical(other.implicit, implicit) || other.implicit == implicit)&&(identical(other.password, password) || other.password == password)&&(identical(other.clientCredentials, clientCredentials) || other.clientCredentials == clientCredentials)&&(identical(other.authorizationCode, authorizationCode) || other.authorizationCode == authorizationCode)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,implicit,password,clientCredentials,authorizationCode); + +@override +String toString() { + return 'OAuthFlows(implicit: $implicit, password: $password, clientCredentials: $clientCredentials, authorizationCode: $authorizationCode)'; +} + + +} + +/// @nodoc +abstract mixin class $OAuthFlowsCopyWith<$Res> { + factory $OAuthFlowsCopyWith(OAuthFlows value, $Res Function(OAuthFlows) _then) = _$OAuthFlowsCopyWithImpl; +@useResult +$Res call({ + OAuthFlow? implicit, OAuthFlow? password, OAuthFlow? clientCredentials, OAuthFlow? authorizationCode +}); + + +$OAuthFlowCopyWith<$Res>? get implicit;$OAuthFlowCopyWith<$Res>? get password;$OAuthFlowCopyWith<$Res>? get clientCredentials;$OAuthFlowCopyWith<$Res>? get authorizationCode; + +} +/// @nodoc +class _$OAuthFlowsCopyWithImpl<$Res> + implements $OAuthFlowsCopyWith<$Res> { + _$OAuthFlowsCopyWithImpl(this._self, this._then); + + final OAuthFlows _self; + final $Res Function(OAuthFlows) _then; + +/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? implicit = freezed,Object? password = freezed,Object? clientCredentials = freezed,Object? authorizationCode = freezed,}) { + return _then(_self.copyWith( +implicit: freezed == implicit ? _self.implicit : implicit // ignore: cast_nullable_to_non_nullable +as OAuthFlow?,password: freezed == password ? _self.password : password // ignore: cast_nullable_to_non_nullable +as OAuthFlow?,clientCredentials: freezed == clientCredentials ? _self.clientCredentials : clientCredentials // ignore: cast_nullable_to_non_nullable +as OAuthFlow?,authorizationCode: freezed == authorizationCode ? _self.authorizationCode : authorizationCode // ignore: cast_nullable_to_non_nullable +as OAuthFlow?, + )); +} +/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get implicit { + if (_self.implicit == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.implicit!, (value) { + return _then(_self.copyWith(implicit: value)); + }); +}/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get password { + if (_self.password == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.password!, (value) { + return _then(_self.copyWith(password: value)); + }); +}/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get clientCredentials { + if (_self.clientCredentials == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.clientCredentials!, (value) { + return _then(_self.copyWith(clientCredentials: value)); + }); +}/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get authorizationCode { + if (_self.authorizationCode == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.authorizationCode!, (value) { + return _then(_self.copyWith(authorizationCode: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [OAuthFlows]. +extension OAuthFlowsPatterns on OAuthFlows { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _OAuthFlows value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _OAuthFlows() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _OAuthFlows value) $default,){ +final _that = this; +switch (_that) { +case _OAuthFlows(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _OAuthFlows value)? $default,){ +final _that = this; +switch (_that) { +case _OAuthFlows() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( OAuthFlow? implicit, OAuthFlow? password, OAuthFlow? clientCredentials, OAuthFlow? authorizationCode)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _OAuthFlows() when $default != null: +return $default(_that.implicit,_that.password,_that.clientCredentials,_that.authorizationCode);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( OAuthFlow? implicit, OAuthFlow? password, OAuthFlow? clientCredentials, OAuthFlow? authorizationCode) $default,) {final _that = this; +switch (_that) { +case _OAuthFlows(): +return $default(_that.implicit,_that.password,_that.clientCredentials,_that.authorizationCode);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( OAuthFlow? implicit, OAuthFlow? password, OAuthFlow? clientCredentials, OAuthFlow? authorizationCode)? $default,) {final _that = this; +switch (_that) { +case _OAuthFlows() when $default != null: +return $default(_that.implicit,_that.password,_that.clientCredentials,_that.authorizationCode);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _OAuthFlows implements OAuthFlows { + const _OAuthFlows({this.implicit, this.password, this.clientCredentials, this.authorizationCode}); + factory _OAuthFlows.fromJson(Map json) => _$OAuthFlowsFromJson(json); + +/// Configuration for the Implicit Grant flow. +@override final OAuthFlow? implicit; +/// Configuration for the Resource Owner Password Credentials Grant flow. +@override final OAuthFlow? password; +/// Configuration for the Client Credentials Grant flow. +@override final OAuthFlow? clientCredentials; +/// Configuration for the Authorization Code Grant flow. +@override final OAuthFlow? authorizationCode; + +/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$OAuthFlowsCopyWith<_OAuthFlows> get copyWith => __$OAuthFlowsCopyWithImpl<_OAuthFlows>(this, _$identity); + +@override +Map toJson() { + return _$OAuthFlowsToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _OAuthFlows&&(identical(other.implicit, implicit) || other.implicit == implicit)&&(identical(other.password, password) || other.password == password)&&(identical(other.clientCredentials, clientCredentials) || other.clientCredentials == clientCredentials)&&(identical(other.authorizationCode, authorizationCode) || other.authorizationCode == authorizationCode)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,implicit,password,clientCredentials,authorizationCode); + +@override +String toString() { + return 'OAuthFlows(implicit: $implicit, password: $password, clientCredentials: $clientCredentials, authorizationCode: $authorizationCode)'; +} + + +} + +/// @nodoc +abstract mixin class _$OAuthFlowsCopyWith<$Res> implements $OAuthFlowsCopyWith<$Res> { + factory _$OAuthFlowsCopyWith(_OAuthFlows value, $Res Function(_OAuthFlows) _then) = __$OAuthFlowsCopyWithImpl; +@override @useResult +$Res call({ + OAuthFlow? implicit, OAuthFlow? password, OAuthFlow? clientCredentials, OAuthFlow? authorizationCode +}); + + +@override $OAuthFlowCopyWith<$Res>? get implicit;@override $OAuthFlowCopyWith<$Res>? get password;@override $OAuthFlowCopyWith<$Res>? get clientCredentials;@override $OAuthFlowCopyWith<$Res>? get authorizationCode; + +} +/// @nodoc +class __$OAuthFlowsCopyWithImpl<$Res> + implements _$OAuthFlowsCopyWith<$Res> { + __$OAuthFlowsCopyWithImpl(this._self, this._then); + + final _OAuthFlows _self; + final $Res Function(_OAuthFlows) _then; + +/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? implicit = freezed,Object? password = freezed,Object? clientCredentials = freezed,Object? authorizationCode = freezed,}) { + return _then(_OAuthFlows( +implicit: freezed == implicit ? _self.implicit : implicit // ignore: cast_nullable_to_non_nullable +as OAuthFlow?,password: freezed == password ? _self.password : password // ignore: cast_nullable_to_non_nullable +as OAuthFlow?,clientCredentials: freezed == clientCredentials ? _self.clientCredentials : clientCredentials // ignore: cast_nullable_to_non_nullable +as OAuthFlow?,authorizationCode: freezed == authorizationCode ? _self.authorizationCode : authorizationCode // ignore: cast_nullable_to_non_nullable +as OAuthFlow?, + )); +} + +/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get implicit { + if (_self.implicit == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.implicit!, (value) { + return _then(_self.copyWith(implicit: value)); + }); +}/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get password { + if (_self.password == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.password!, (value) { + return _then(_self.copyWith(password: value)); + }); +}/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get clientCredentials { + if (_self.clientCredentials == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.clientCredentials!, (value) { + return _then(_self.copyWith(clientCredentials: value)); + }); +}/// Create a copy of OAuthFlows +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith<$Res>? get authorizationCode { + if (_self.authorizationCode == null) { + return null; + } + + return $OAuthFlowCopyWith<$Res>(_self.authorizationCode!, (value) { + return _then(_self.copyWith(authorizationCode: value)); + }); +} +} + + +/// @nodoc +mixin _$OAuthFlow { + +/// The Authorization URL for this flow. +/// +/// Required for `implicit` and `authorizationCode` flows. + String? get authorizationUrl;/// The Token URL for this flow. +/// +/// Required for `password`, `clientCredentials`, and `authorizationCode` +/// flows. + String? get tokenUrl;/// The Refresh URL to obtain a new access token. + String? get refreshUrl;/// A map of available scopes for this flow. +/// +/// The keys are scope names, and the values are human-readable +/// descriptions. + Map get scopes; +/// Create a copy of OAuthFlow +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$OAuthFlowCopyWith get copyWith => _$OAuthFlowCopyWithImpl(this as OAuthFlow, _$identity); + + /// Serializes this OAuthFlow to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is OAuthFlow&&(identical(other.authorizationUrl, authorizationUrl) || other.authorizationUrl == authorizationUrl)&&(identical(other.tokenUrl, tokenUrl) || other.tokenUrl == tokenUrl)&&(identical(other.refreshUrl, refreshUrl) || other.refreshUrl == refreshUrl)&&const DeepCollectionEquality().equals(other.scopes, scopes)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,authorizationUrl,tokenUrl,refreshUrl,const DeepCollectionEquality().hash(scopes)); + +@override +String toString() { + return 'OAuthFlow(authorizationUrl: $authorizationUrl, tokenUrl: $tokenUrl, refreshUrl: $refreshUrl, scopes: $scopes)'; +} + + +} + +/// @nodoc +abstract mixin class $OAuthFlowCopyWith<$Res> { + factory $OAuthFlowCopyWith(OAuthFlow value, $Res Function(OAuthFlow) _then) = _$OAuthFlowCopyWithImpl; +@useResult +$Res call({ + String? authorizationUrl, String? tokenUrl, String? refreshUrl, Map scopes +}); + + + + +} +/// @nodoc +class _$OAuthFlowCopyWithImpl<$Res> + implements $OAuthFlowCopyWith<$Res> { + _$OAuthFlowCopyWithImpl(this._self, this._then); + + final OAuthFlow _self; + final $Res Function(OAuthFlow) _then; + +/// Create a copy of OAuthFlow +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? authorizationUrl = freezed,Object? tokenUrl = freezed,Object? refreshUrl = freezed,Object? scopes = null,}) { + return _then(_self.copyWith( +authorizationUrl: freezed == authorizationUrl ? _self.authorizationUrl : authorizationUrl // ignore: cast_nullable_to_non_nullable +as String?,tokenUrl: freezed == tokenUrl ? _self.tokenUrl : tokenUrl // ignore: cast_nullable_to_non_nullable +as String?,refreshUrl: freezed == refreshUrl ? _self.refreshUrl : refreshUrl // ignore: cast_nullable_to_non_nullable +as String?,scopes: null == scopes ? _self.scopes : scopes // ignore: cast_nullable_to_non_nullable +as Map, + )); +} + +} + + +/// Adds pattern-matching-related methods to [OAuthFlow]. +extension OAuthFlowPatterns on OAuthFlow { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _OAuthFlow value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _OAuthFlow() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _OAuthFlow value) $default,){ +final _that = this; +switch (_that) { +case _OAuthFlow(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _OAuthFlow value)? $default,){ +final _that = this; +switch (_that) { +case _OAuthFlow() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String? authorizationUrl, String? tokenUrl, String? refreshUrl, Map scopes)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _OAuthFlow() when $default != null: +return $default(_that.authorizationUrl,_that.tokenUrl,_that.refreshUrl,_that.scopes);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String? authorizationUrl, String? tokenUrl, String? refreshUrl, Map scopes) $default,) {final _that = this; +switch (_that) { +case _OAuthFlow(): +return $default(_that.authorizationUrl,_that.tokenUrl,_that.refreshUrl,_that.scopes);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String? authorizationUrl, String? tokenUrl, String? refreshUrl, Map scopes)? $default,) {final _that = this; +switch (_that) { +case _OAuthFlow() when $default != null: +return $default(_that.authorizationUrl,_that.tokenUrl,_that.refreshUrl,_that.scopes);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _OAuthFlow implements OAuthFlow { + const _OAuthFlow({this.authorizationUrl, this.tokenUrl, this.refreshUrl, required final Map scopes}): _scopes = scopes; + factory _OAuthFlow.fromJson(Map json) => _$OAuthFlowFromJson(json); + +/// The Authorization URL for this flow. +/// +/// Required for `implicit` and `authorizationCode` flows. +@override final String? authorizationUrl; +/// The Token URL for this flow. +/// +/// Required for `password`, `clientCredentials`, and `authorizationCode` +/// flows. +@override final String? tokenUrl; +/// The Refresh URL to obtain a new access token. +@override final String? refreshUrl; +/// A map of available scopes for this flow. +/// +/// The keys are scope names, and the values are human-readable +/// descriptions. + final Map _scopes; +/// A map of available scopes for this flow. +/// +/// The keys are scope names, and the values are human-readable +/// descriptions. +@override Map get scopes { + if (_scopes is EqualUnmodifiableMapView) return _scopes; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_scopes); +} + + +/// Create a copy of OAuthFlow +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$OAuthFlowCopyWith<_OAuthFlow> get copyWith => __$OAuthFlowCopyWithImpl<_OAuthFlow>(this, _$identity); + +@override +Map toJson() { + return _$OAuthFlowToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _OAuthFlow&&(identical(other.authorizationUrl, authorizationUrl) || other.authorizationUrl == authorizationUrl)&&(identical(other.tokenUrl, tokenUrl) || other.tokenUrl == tokenUrl)&&(identical(other.refreshUrl, refreshUrl) || other.refreshUrl == refreshUrl)&&const DeepCollectionEquality().equals(other._scopes, _scopes)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,authorizationUrl,tokenUrl,refreshUrl,const DeepCollectionEquality().hash(_scopes)); + +@override +String toString() { + return 'OAuthFlow(authorizationUrl: $authorizationUrl, tokenUrl: $tokenUrl, refreshUrl: $refreshUrl, scopes: $scopes)'; +} + + +} + +/// @nodoc +abstract mixin class _$OAuthFlowCopyWith<$Res> implements $OAuthFlowCopyWith<$Res> { + factory _$OAuthFlowCopyWith(_OAuthFlow value, $Res Function(_OAuthFlow) _then) = __$OAuthFlowCopyWithImpl; +@override @useResult +$Res call({ + String? authorizationUrl, String? tokenUrl, String? refreshUrl, Map scopes +}); + + + + +} +/// @nodoc +class __$OAuthFlowCopyWithImpl<$Res> + implements _$OAuthFlowCopyWith<$Res> { + __$OAuthFlowCopyWithImpl(this._self, this._then); + + final _OAuthFlow _self; + final $Res Function(_OAuthFlow) _then; + +/// Create a copy of OAuthFlow +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? authorizationUrl = freezed,Object? tokenUrl = freezed,Object? refreshUrl = freezed,Object? scopes = null,}) { + return _then(_OAuthFlow( +authorizationUrl: freezed == authorizationUrl ? _self.authorizationUrl : authorizationUrl // ignore: cast_nullable_to_non_nullable +as String?,tokenUrl: freezed == tokenUrl ? _self.tokenUrl : tokenUrl // ignore: cast_nullable_to_non_nullable +as String?,refreshUrl: freezed == refreshUrl ? _self.refreshUrl : refreshUrl // ignore: cast_nullable_to_non_nullable +as String?,scopes: null == scopes ? _self._scopes : scopes // ignore: cast_nullable_to_non_nullable +as Map, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/security_scheme.g.dart b/packages/a2a_dart/lib/src/core/security_scheme.g.dart new file mode 100644 index 000000000..9f50690e6 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/security_scheme.g.dart @@ -0,0 +1,127 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'security_scheme.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +APIKeySecurityScheme _$APIKeySecuritySchemeFromJson( + Map json, +) => APIKeySecurityScheme( + type: json['type'] as String? ?? 'apiKey', + description: json['description'] as String?, + name: json['name'] as String, + in_: json['in'] as String, +); + +Map _$APIKeySecuritySchemeToJson( + APIKeySecurityScheme instance, +) => { + 'type': instance.type, + 'description': instance.description, + 'name': instance.name, + 'in': instance.in_, +}; + +HttpAuthSecurityScheme _$HttpAuthSecuritySchemeFromJson( + Map json, +) => HttpAuthSecurityScheme( + type: json['type'] as String? ?? 'http', + description: json['description'] as String?, + scheme: json['scheme'] as String, + bearerFormat: json['bearerFormat'] as String?, +); + +Map _$HttpAuthSecuritySchemeToJson( + HttpAuthSecurityScheme instance, +) => { + 'type': instance.type, + 'description': instance.description, + 'scheme': instance.scheme, + 'bearerFormat': instance.bearerFormat, +}; + +OAuth2SecurityScheme _$OAuth2SecuritySchemeFromJson( + Map json, +) => OAuth2SecurityScheme( + type: json['type'] as String? ?? 'oauth2', + description: json['description'] as String?, + flows: OAuthFlows.fromJson(json['flows'] as Map), +); + +Map _$OAuth2SecuritySchemeToJson( + OAuth2SecurityScheme instance, +) => { + 'type': instance.type, + 'description': instance.description, + 'flows': instance.flows.toJson(), +}; + +OpenIdConnectSecurityScheme _$OpenIdConnectSecuritySchemeFromJson( + Map json, +) => OpenIdConnectSecurityScheme( + type: json['type'] as String? ?? 'openIdConnect', + description: json['description'] as String?, + openIdConnectUrl: json['openIdConnectUrl'] as String, +); + +Map _$OpenIdConnectSecuritySchemeToJson( + OpenIdConnectSecurityScheme instance, +) => { + 'type': instance.type, + 'description': instance.description, + 'openIdConnectUrl': instance.openIdConnectUrl, +}; + +MutualTlsSecurityScheme _$MutualTlsSecuritySchemeFromJson( + Map json, +) => MutualTlsSecurityScheme( + type: json['type'] as String? ?? 'mutualTls', + description: json['description'] as String?, +); + +Map _$MutualTlsSecuritySchemeToJson( + MutualTlsSecurityScheme instance, +) => { + 'type': instance.type, + 'description': instance.description, +}; + +_OAuthFlows _$OAuthFlowsFromJson(Map json) => _OAuthFlows( + implicit: json['implicit'] == null + ? null + : OAuthFlow.fromJson(json['implicit'] as Map), + password: json['password'] == null + ? null + : OAuthFlow.fromJson(json['password'] as Map), + clientCredentials: json['clientCredentials'] == null + ? null + : OAuthFlow.fromJson(json['clientCredentials'] as Map), + authorizationCode: json['authorizationCode'] == null + ? null + : OAuthFlow.fromJson(json['authorizationCode'] as Map), +); + +Map _$OAuthFlowsToJson(_OAuthFlows instance) => + { + 'implicit': instance.implicit?.toJson(), + 'password': instance.password?.toJson(), + 'clientCredentials': instance.clientCredentials?.toJson(), + 'authorizationCode': instance.authorizationCode?.toJson(), + }; + +_OAuthFlow _$OAuthFlowFromJson(Map json) => _OAuthFlow( + authorizationUrl: json['authorizationUrl'] as String?, + tokenUrl: json['tokenUrl'] as String?, + refreshUrl: json['refreshUrl'] as String?, + scopes: Map.from(json['scopes'] as Map), +); + +Map _$OAuthFlowToJson(_OAuthFlow instance) => + { + 'authorizationUrl': instance.authorizationUrl, + 'tokenUrl': instance.tokenUrl, + 'refreshUrl': instance.refreshUrl, + 'scopes': instance.scopes, + }; diff --git a/packages/a2a_dart/lib/src/core/task.dart b/packages/a2a_dart/lib/src/core/task.dart new file mode 100644 index 000000000..e2bdcfada --- /dev/null +++ b/packages/a2a_dart/lib/src/core/task.dart @@ -0,0 +1,143 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'message.dart'; +import 'part.dart'; + +part 'task.freezed.dart'; + +part 'task.g.dart'; + +/// Represents a stateful operation or conversation between a client and an +/// agent. +/// +/// A [Task] encapsulates the entire lifecycle of an interaction, including its +/// current status, history of messages, and any generated artifacts. +@freezed +abstract class Task with _$Task { + /// Creates a [Task] instance. + const factory Task({ + /// A unique identifier (e.g., UUID) for the task. + /// + /// This ID is typically generated by the server when a new task is created. + required String id, + + /// A server-generated unique identifier (e.g., UUID) for grouping related + /// tasks or interactions, forming a conversation context. + required String contextId, + + /// The current status of the task, including its state and any associated + /// message. + required TaskStatus status, + + /// An optional list of [Message] objects representing the conversation + /// history of the task. + List? history, + + /// An optional collection of [Artifact]s produced by the agent during the + /// task's execution. + List? artifacts, + + /// Optional metadata for extensions, as a map where the key is an + /// extension-specific identifier. + Map? metadata, + + /// The timestamp of the last update to the task, in milliseconds since the + /// Unix epoch. + int? lastUpdated, + + /// The type discriminator for this object, always 'task'. + @Default('task') String kind, + }) = _Task; + + /// Deserializes a [Task] instance from a JSON object. + factory Task.fromJson(Map json) => _$TaskFromJson(json); +} + +/// Represents the status of a [Task] at a specific point in time. +@freezed +abstract class TaskStatus with _$TaskStatus { + /// Creates a [TaskStatus] instance. + const factory TaskStatus({ + /// The current state in the task's lifecycle. + required TaskState state, + + /// An optional, human-readable [Message] providing more details about the + /// current status (e.g., an error message or a prompt for input). + Message? message, + + /// The timestamp when this status was recorded, in milliseconds since the + /// Unix epoch. + String? timestamp, + }) = _TaskStatus; + + /// Deserializes a [TaskStatus] instance from a JSON object. + factory TaskStatus.fromJson(Map json) => + _$TaskStatusFromJson(json); +} + +/// Defines the possible lifecycle states of a [Task]. +enum TaskState { + /// The task has been received by the server but not yet started. + submitted, + + /// The agent is actively processing the task. + working, + + /// The task is paused, awaiting further input from the client. + inputRequired, + + /// The task has been successfully completed by the agent. + completed, + + /// The task was canceled, typically by a client request. + canceled, + + /// The task failed due to an error during execution. + failed, + + /// The task was rejected by the agent before execution began (e.g., due to + /// invalid parameters or permissions). + rejected, + + /// The task cannot proceed without additional authentication or + /// authorization. + authRequired, + + /// The task is in an unknown or indeterminate state. + unknown, +} + +/// Represents a file, data structure, or other resource generated by an agent +/// during a [Task]. +@freezed +abstract class Artifact with _$Artifact { + /// Creates an [Artifact] instance. + const factory Artifact({ + /// A unique identifier for this artifact within the scope of the task. + required String artifactId, + + /// An optional, human-readable name for the artifact. + String? name, + + /// An optional, human-readable description of the artifact's content or + /// purpose. + String? description, + + /// A list of [Part] objects that constitute the content of the artifact. + required List parts, + + /// Optional metadata for extensions. + Map? metadata, + + /// Optional list of URIs for extensions that are relevant to this artifact. + List? extensions, + }) = _Artifact; + + /// Deserializes an [Artifact] instance from a JSON object. + factory Artifact.fromJson(Map json) => + _$ArtifactFromJson(json); +} diff --git a/packages/a2a_dart/lib/src/core/task.freezed.dart b/packages/a2a_dart/lib/src/core/task.freezed.dart new file mode 100644 index 000000000..cee491ea6 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/task.freezed.dart @@ -0,0 +1,998 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'task.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$Task { + +/// A unique identifier (e.g., UUID) for the task. +/// +/// This ID is typically generated by the server when a new task is created. + String get id;/// A server-generated unique identifier (e.g., UUID) for grouping related +/// tasks or interactions, forming a conversation context. + String get contextId;/// The current status of the task, including its state and any associated +/// message. + TaskStatus get status;/// An optional list of [Message] objects representing the conversation +/// history of the task. + List? get history;/// An optional collection of [Artifact]s produced by the agent during the +/// task's execution. + List? get artifacts;/// Optional metadata for extensions, as a map where the key is an +/// extension-specific identifier. + Map? get metadata;/// The timestamp of the last update to the task, in milliseconds since the +/// Unix epoch. + int? get lastUpdated;/// The type discriminator for this object, always 'task'. + String get kind; +/// Create a copy of Task +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TaskCopyWith get copyWith => _$TaskCopyWithImpl(this as Task, _$identity); + + /// Serializes this Task to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Task&&(identical(other.id, id) || other.id == id)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.status, status) || other.status == status)&&const DeepCollectionEquality().equals(other.history, history)&&const DeepCollectionEquality().equals(other.artifacts, artifacts)&&const DeepCollectionEquality().equals(other.metadata, metadata)&&(identical(other.lastUpdated, lastUpdated) || other.lastUpdated == lastUpdated)&&(identical(other.kind, kind) || other.kind == kind)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,contextId,status,const DeepCollectionEquality().hash(history),const DeepCollectionEquality().hash(artifacts),const DeepCollectionEquality().hash(metadata),lastUpdated,kind); + +@override +String toString() { + return 'Task(id: $id, contextId: $contextId, status: $status, history: $history, artifacts: $artifacts, metadata: $metadata, lastUpdated: $lastUpdated, kind: $kind)'; +} + + +} + +/// @nodoc +abstract mixin class $TaskCopyWith<$Res> { + factory $TaskCopyWith(Task value, $Res Function(Task) _then) = _$TaskCopyWithImpl; +@useResult +$Res call({ + String id, String contextId, TaskStatus status, List? history, List? artifacts, Map? metadata, int? lastUpdated, String kind +}); + + +$TaskStatusCopyWith<$Res> get status; + +} +/// @nodoc +class _$TaskCopyWithImpl<$Res> + implements $TaskCopyWith<$Res> { + _$TaskCopyWithImpl(this._self, this._then); + + final Task _self; + final $Res Function(Task) _then; + +/// Create a copy of Task +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? contextId = null,Object? status = null,Object? history = freezed,Object? artifacts = freezed,Object? metadata = freezed,Object? lastUpdated = freezed,Object? kind = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as TaskStatus,history: freezed == history ? _self.history : history // ignore: cast_nullable_to_non_nullable +as List?,artifacts: freezed == artifacts ? _self.artifacts : artifacts // ignore: cast_nullable_to_non_nullable +as List?,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?,lastUpdated: freezed == lastUpdated ? _self.lastUpdated : lastUpdated // ignore: cast_nullable_to_non_nullable +as int?,kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String, + )); +} +/// Create a copy of Task +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$TaskStatusCopyWith<$Res> get status { + + return $TaskStatusCopyWith<$Res>(_self.status, (value) { + return _then(_self.copyWith(status: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [Task]. +extension TaskPatterns on Task { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _Task value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _Task() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _Task value) $default,){ +final _that = this; +switch (_that) { +case _Task(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _Task value)? $default,){ +final _that = this; +switch (_that) { +case _Task() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String contextId, TaskStatus status, List? history, List? artifacts, Map? metadata, int? lastUpdated, String kind)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _Task() when $default != null: +return $default(_that.id,_that.contextId,_that.status,_that.history,_that.artifacts,_that.metadata,_that.lastUpdated,_that.kind);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String contextId, TaskStatus status, List? history, List? artifacts, Map? metadata, int? lastUpdated, String kind) $default,) {final _that = this; +switch (_that) { +case _Task(): +return $default(_that.id,_that.contextId,_that.status,_that.history,_that.artifacts,_that.metadata,_that.lastUpdated,_that.kind);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String contextId, TaskStatus status, List? history, List? artifacts, Map? metadata, int? lastUpdated, String kind)? $default,) {final _that = this; +switch (_that) { +case _Task() when $default != null: +return $default(_that.id,_that.contextId,_that.status,_that.history,_that.artifacts,_that.metadata,_that.lastUpdated,_that.kind);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _Task implements Task { + const _Task({required this.id, required this.contextId, required this.status, final List? history, final List? artifacts, final Map? metadata, this.lastUpdated, this.kind = 'task'}): _history = history,_artifacts = artifacts,_metadata = metadata; + factory _Task.fromJson(Map json) => _$TaskFromJson(json); + +/// A unique identifier (e.g., UUID) for the task. +/// +/// This ID is typically generated by the server when a new task is created. +@override final String id; +/// A server-generated unique identifier (e.g., UUID) for grouping related +/// tasks or interactions, forming a conversation context. +@override final String contextId; +/// The current status of the task, including its state and any associated +/// message. +@override final TaskStatus status; +/// An optional list of [Message] objects representing the conversation +/// history of the task. + final List? _history; +/// An optional list of [Message] objects representing the conversation +/// history of the task. +@override List? get history { + final value = _history; + if (value == null) return null; + if (_history is EqualUnmodifiableListView) return _history; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// An optional collection of [Artifact]s produced by the agent during the +/// task's execution. + final List? _artifacts; +/// An optional collection of [Artifact]s produced by the agent during the +/// task's execution. +@override List? get artifacts { + final value = _artifacts; + if (value == null) return null; + if (_artifacts is EqualUnmodifiableListView) return _artifacts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + +/// Optional metadata for extensions, as a map where the key is an +/// extension-specific identifier. + final Map? _metadata; +/// Optional metadata for extensions, as a map where the key is an +/// extension-specific identifier. +@override Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + +/// The timestamp of the last update to the task, in milliseconds since the +/// Unix epoch. +@override final int? lastUpdated; +/// The type discriminator for this object, always 'task'. +@override@JsonKey() final String kind; + +/// Create a copy of Task +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$TaskCopyWith<_Task> get copyWith => __$TaskCopyWithImpl<_Task>(this, _$identity); + +@override +Map toJson() { + return _$TaskToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Task&&(identical(other.id, id) || other.id == id)&&(identical(other.contextId, contextId) || other.contextId == contextId)&&(identical(other.status, status) || other.status == status)&&const DeepCollectionEquality().equals(other._history, _history)&&const DeepCollectionEquality().equals(other._artifacts, _artifacts)&&const DeepCollectionEquality().equals(other._metadata, _metadata)&&(identical(other.lastUpdated, lastUpdated) || other.lastUpdated == lastUpdated)&&(identical(other.kind, kind) || other.kind == kind)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,id,contextId,status,const DeepCollectionEquality().hash(_history),const DeepCollectionEquality().hash(_artifacts),const DeepCollectionEquality().hash(_metadata),lastUpdated,kind); + +@override +String toString() { + return 'Task(id: $id, contextId: $contextId, status: $status, history: $history, artifacts: $artifacts, metadata: $metadata, lastUpdated: $lastUpdated, kind: $kind)'; +} + + +} + +/// @nodoc +abstract mixin class _$TaskCopyWith<$Res> implements $TaskCopyWith<$Res> { + factory _$TaskCopyWith(_Task value, $Res Function(_Task) _then) = __$TaskCopyWithImpl; +@override @useResult +$Res call({ + String id, String contextId, TaskStatus status, List? history, List? artifacts, Map? metadata, int? lastUpdated, String kind +}); + + +@override $TaskStatusCopyWith<$Res> get status; + +} +/// @nodoc +class __$TaskCopyWithImpl<$Res> + implements _$TaskCopyWith<$Res> { + __$TaskCopyWithImpl(this._self, this._then); + + final _Task _self; + final $Res Function(_Task) _then; + +/// Create a copy of Task +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? contextId = null,Object? status = null,Object? history = freezed,Object? artifacts = freezed,Object? metadata = freezed,Object? lastUpdated = freezed,Object? kind = null,}) { + return _then(_Task( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,contextId: null == contextId ? _self.contextId : contextId // ignore: cast_nullable_to_non_nullable +as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable +as TaskStatus,history: freezed == history ? _self._history : history // ignore: cast_nullable_to_non_nullable +as List?,artifacts: freezed == artifacts ? _self._artifacts : artifacts // ignore: cast_nullable_to_non_nullable +as List?,metadata: freezed == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?,lastUpdated: freezed == lastUpdated ? _self.lastUpdated : lastUpdated // ignore: cast_nullable_to_non_nullable +as int?,kind: null == kind ? _self.kind : kind // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +/// Create a copy of Task +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$TaskStatusCopyWith<$Res> get status { + + return $TaskStatusCopyWith<$Res>(_self.status, (value) { + return _then(_self.copyWith(status: value)); + }); +} +} + + +/// @nodoc +mixin _$TaskStatus { + +/// The current state in the task's lifecycle. + TaskState get state;/// An optional, human-readable [Message] providing more details about the +/// current status (e.g., an error message or a prompt for input). + Message? get message;/// The timestamp when this status was recorded, in milliseconds since the +/// Unix epoch. + String? get timestamp; +/// Create a copy of TaskStatus +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$TaskStatusCopyWith get copyWith => _$TaskStatusCopyWithImpl(this as TaskStatus, _$identity); + + /// Serializes this TaskStatus to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is TaskStatus&&(identical(other.state, state) || other.state == state)&&(identical(other.message, message) || other.message == message)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,state,message,timestamp); + +@override +String toString() { + return 'TaskStatus(state: $state, message: $message, timestamp: $timestamp)'; +} + + +} + +/// @nodoc +abstract mixin class $TaskStatusCopyWith<$Res> { + factory $TaskStatusCopyWith(TaskStatus value, $Res Function(TaskStatus) _then) = _$TaskStatusCopyWithImpl; +@useResult +$Res call({ + TaskState state, Message? message, String? timestamp +}); + + +$MessageCopyWith<$Res>? get message; + +} +/// @nodoc +class _$TaskStatusCopyWithImpl<$Res> + implements $TaskStatusCopyWith<$Res> { + _$TaskStatusCopyWithImpl(this._self, this._then); + + final TaskStatus _self; + final $Res Function(TaskStatus) _then; + +/// Create a copy of TaskStatus +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? state = null,Object? message = freezed,Object? timestamp = freezed,}) { + return _then(_self.copyWith( +state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable +as TaskState,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as Message?,timestamp: freezed == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable +as String?, + )); +} +/// Create a copy of TaskStatus +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$MessageCopyWith<$Res>? get message { + if (_self.message == null) { + return null; + } + + return $MessageCopyWith<$Res>(_self.message!, (value) { + return _then(_self.copyWith(message: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [TaskStatus]. +extension TaskStatusPatterns on TaskStatus { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _TaskStatus value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _TaskStatus() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _TaskStatus value) $default,){ +final _that = this; +switch (_that) { +case _TaskStatus(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _TaskStatus value)? $default,){ +final _that = this; +switch (_that) { +case _TaskStatus() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( TaskState state, Message? message, String? timestamp)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _TaskStatus() when $default != null: +return $default(_that.state,_that.message,_that.timestamp);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( TaskState state, Message? message, String? timestamp) $default,) {final _that = this; +switch (_that) { +case _TaskStatus(): +return $default(_that.state,_that.message,_that.timestamp);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( TaskState state, Message? message, String? timestamp)? $default,) {final _that = this; +switch (_that) { +case _TaskStatus() when $default != null: +return $default(_that.state,_that.message,_that.timestamp);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _TaskStatus implements TaskStatus { + const _TaskStatus({required this.state, this.message, this.timestamp}); + factory _TaskStatus.fromJson(Map json) => _$TaskStatusFromJson(json); + +/// The current state in the task's lifecycle. +@override final TaskState state; +/// An optional, human-readable [Message] providing more details about the +/// current status (e.g., an error message or a prompt for input). +@override final Message? message; +/// The timestamp when this status was recorded, in milliseconds since the +/// Unix epoch. +@override final String? timestamp; + +/// Create a copy of TaskStatus +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$TaskStatusCopyWith<_TaskStatus> get copyWith => __$TaskStatusCopyWithImpl<_TaskStatus>(this, _$identity); + +@override +Map toJson() { + return _$TaskStatusToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _TaskStatus&&(identical(other.state, state) || other.state == state)&&(identical(other.message, message) || other.message == message)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,state,message,timestamp); + +@override +String toString() { + return 'TaskStatus(state: $state, message: $message, timestamp: $timestamp)'; +} + + +} + +/// @nodoc +abstract mixin class _$TaskStatusCopyWith<$Res> implements $TaskStatusCopyWith<$Res> { + factory _$TaskStatusCopyWith(_TaskStatus value, $Res Function(_TaskStatus) _then) = __$TaskStatusCopyWithImpl; +@override @useResult +$Res call({ + TaskState state, Message? message, String? timestamp +}); + + +@override $MessageCopyWith<$Res>? get message; + +} +/// @nodoc +class __$TaskStatusCopyWithImpl<$Res> + implements _$TaskStatusCopyWith<$Res> { + __$TaskStatusCopyWithImpl(this._self, this._then); + + final _TaskStatus _self; + final $Res Function(_TaskStatus) _then; + +/// Create a copy of TaskStatus +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? state = null,Object? message = freezed,Object? timestamp = freezed,}) { + return _then(_TaskStatus( +state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable +as TaskState,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable +as Message?,timestamp: freezed == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +/// Create a copy of TaskStatus +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$MessageCopyWith<$Res>? get message { + if (_self.message == null) { + return null; + } + + return $MessageCopyWith<$Res>(_self.message!, (value) { + return _then(_self.copyWith(message: value)); + }); +} +} + + +/// @nodoc +mixin _$Artifact { + +/// A unique identifier for this artifact within the scope of the task. + String get artifactId;/// An optional, human-readable name for the artifact. + String? get name;/// An optional, human-readable description of the artifact's content or +/// purpose. + String? get description;/// A list of [Part] objects that constitute the content of the artifact. + List get parts;/// Optional metadata for extensions. + Map? get metadata;/// Optional list of URIs for extensions that are relevant to this artifact. + List? get extensions; +/// Create a copy of Artifact +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ArtifactCopyWith get copyWith => _$ArtifactCopyWithImpl(this as Artifact, _$identity); + + /// Serializes this Artifact to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Artifact&&(identical(other.artifactId, artifactId) || other.artifactId == artifactId)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.parts, parts)&&const DeepCollectionEquality().equals(other.metadata, metadata)&&const DeepCollectionEquality().equals(other.extensions, extensions)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,artifactId,name,description,const DeepCollectionEquality().hash(parts),const DeepCollectionEquality().hash(metadata),const DeepCollectionEquality().hash(extensions)); + +@override +String toString() { + return 'Artifact(artifactId: $artifactId, name: $name, description: $description, parts: $parts, metadata: $metadata, extensions: $extensions)'; +} + + +} + +/// @nodoc +abstract mixin class $ArtifactCopyWith<$Res> { + factory $ArtifactCopyWith(Artifact value, $Res Function(Artifact) _then) = _$ArtifactCopyWithImpl; +@useResult +$Res call({ + String artifactId, String? name, String? description, List parts, Map? metadata, List? extensions +}); + + + + +} +/// @nodoc +class _$ArtifactCopyWithImpl<$Res> + implements $ArtifactCopyWith<$Res> { + _$ArtifactCopyWithImpl(this._self, this._then); + + final Artifact _self; + final $Res Function(Artifact) _then; + +/// Create a copy of Artifact +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? artifactId = null,Object? name = freezed,Object? description = freezed,Object? parts = null,Object? metadata = freezed,Object? extensions = freezed,}) { + return _then(_self.copyWith( +artifactId: null == artifactId ? _self.artifactId : artifactId // ignore: cast_nullable_to_non_nullable +as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,parts: null == parts ? _self.parts : parts // ignore: cast_nullable_to_non_nullable +as List,metadata: freezed == metadata ? _self.metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?,extensions: freezed == extensions ? _self.extensions : extensions // ignore: cast_nullable_to_non_nullable +as List?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [Artifact]. +extension ArtifactPatterns on Artifact { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _Artifact value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _Artifact() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _Artifact value) $default,){ +final _that = this; +switch (_that) { +case _Artifact(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _Artifact value)? $default,){ +final _that = this; +switch (_that) { +case _Artifact() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String artifactId, String? name, String? description, List parts, Map? metadata, List? extensions)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _Artifact() when $default != null: +return $default(_that.artifactId,_that.name,_that.description,_that.parts,_that.metadata,_that.extensions);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String artifactId, String? name, String? description, List parts, Map? metadata, List? extensions) $default,) {final _that = this; +switch (_that) { +case _Artifact(): +return $default(_that.artifactId,_that.name,_that.description,_that.parts,_that.metadata,_that.extensions);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String artifactId, String? name, String? description, List parts, Map? metadata, List? extensions)? $default,) {final _that = this; +switch (_that) { +case _Artifact() when $default != null: +return $default(_that.artifactId,_that.name,_that.description,_that.parts,_that.metadata,_that.extensions);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _Artifact implements Artifact { + const _Artifact({required this.artifactId, this.name, this.description, required final List parts, final Map? metadata, final List? extensions}): _parts = parts,_metadata = metadata,_extensions = extensions; + factory _Artifact.fromJson(Map json) => _$ArtifactFromJson(json); + +/// A unique identifier for this artifact within the scope of the task. +@override final String artifactId; +/// An optional, human-readable name for the artifact. +@override final String? name; +/// An optional, human-readable description of the artifact's content or +/// purpose. +@override final String? description; +/// A list of [Part] objects that constitute the content of the artifact. + final List _parts; +/// A list of [Part] objects that constitute the content of the artifact. +@override List get parts { + if (_parts is EqualUnmodifiableListView) return _parts; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_parts); +} + +/// Optional metadata for extensions. + final Map? _metadata; +/// Optional metadata for extensions. +@override Map? get metadata { + final value = _metadata; + if (value == null) return null; + if (_metadata is EqualUnmodifiableMapView) return _metadata; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); +} + +/// Optional list of URIs for extensions that are relevant to this artifact. + final List? _extensions; +/// Optional list of URIs for extensions that are relevant to this artifact. +@override List? get extensions { + final value = _extensions; + if (value == null) return null; + if (_extensions is EqualUnmodifiableListView) return _extensions; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + + +/// Create a copy of Artifact +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ArtifactCopyWith<_Artifact> get copyWith => __$ArtifactCopyWithImpl<_Artifact>(this, _$identity); + +@override +Map toJson() { + return _$ArtifactToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Artifact&&(identical(other.artifactId, artifactId) || other.artifactId == artifactId)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._parts, _parts)&&const DeepCollectionEquality().equals(other._metadata, _metadata)&&const DeepCollectionEquality().equals(other._extensions, _extensions)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,artifactId,name,description,const DeepCollectionEquality().hash(_parts),const DeepCollectionEquality().hash(_metadata),const DeepCollectionEquality().hash(_extensions)); + +@override +String toString() { + return 'Artifact(artifactId: $artifactId, name: $name, description: $description, parts: $parts, metadata: $metadata, extensions: $extensions)'; +} + + +} + +/// @nodoc +abstract mixin class _$ArtifactCopyWith<$Res> implements $ArtifactCopyWith<$Res> { + factory _$ArtifactCopyWith(_Artifact value, $Res Function(_Artifact) _then) = __$ArtifactCopyWithImpl; +@override @useResult +$Res call({ + String artifactId, String? name, String? description, List parts, Map? metadata, List? extensions +}); + + + + +} +/// @nodoc +class __$ArtifactCopyWithImpl<$Res> + implements _$ArtifactCopyWith<$Res> { + __$ArtifactCopyWithImpl(this._self, this._then); + + final _Artifact _self; + final $Res Function(_Artifact) _then; + +/// Create a copy of Artifact +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? artifactId = null,Object? name = freezed,Object? description = freezed,Object? parts = null,Object? metadata = freezed,Object? extensions = freezed,}) { + return _then(_Artifact( +artifactId: null == artifactId ? _self.artifactId : artifactId // ignore: cast_nullable_to_non_nullable +as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable +as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String?,parts: null == parts ? _self._parts : parts // ignore: cast_nullable_to_non_nullable +as List,metadata: freezed == metadata ? _self._metadata : metadata // ignore: cast_nullable_to_non_nullable +as Map?,extensions: freezed == extensions ? _self._extensions : extensions // ignore: cast_nullable_to_non_nullable +as List?, + )); +} + + +} + +// dart format on diff --git a/packages/a2a_dart/lib/src/core/task.g.dart b/packages/a2a_dart/lib/src/core/task.g.dart new file mode 100644 index 000000000..b71964964 --- /dev/null +++ b/packages/a2a_dart/lib/src/core/task.g.dart @@ -0,0 +1,82 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'task.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_Task _$TaskFromJson(Map json) => _Task( + id: json['id'] as String, + contextId: json['contextId'] as String, + status: TaskStatus.fromJson(json['status'] as Map), + history: (json['history'] as List?) + ?.map((e) => Message.fromJson(e as Map)) + .toList(), + artifacts: (json['artifacts'] as List?) + ?.map((e) => Artifact.fromJson(e as Map)) + .toList(), + metadata: json['metadata'] as Map?, + lastUpdated: (json['lastUpdated'] as num?)?.toInt(), + kind: json['kind'] as String? ?? 'task', +); + +Map _$TaskToJson(_Task instance) => { + 'id': instance.id, + 'contextId': instance.contextId, + 'status': instance.status.toJson(), + 'history': instance.history?.map((e) => e.toJson()).toList(), + 'artifacts': instance.artifacts?.map((e) => e.toJson()).toList(), + 'metadata': instance.metadata, + 'lastUpdated': instance.lastUpdated, + 'kind': instance.kind, +}; + +_TaskStatus _$TaskStatusFromJson(Map json) => _TaskStatus( + state: $enumDecode(_$TaskStateEnumMap, json['state']), + message: json['message'] == null + ? null + : Message.fromJson(json['message'] as Map), + timestamp: json['timestamp'] as String?, +); + +Map _$TaskStatusToJson(_TaskStatus instance) => + { + 'state': _$TaskStateEnumMap[instance.state]!, + 'message': instance.message?.toJson(), + 'timestamp': instance.timestamp, + }; + +const _$TaskStateEnumMap = { + TaskState.submitted: 'submitted', + TaskState.working: 'working', + TaskState.inputRequired: 'inputRequired', + TaskState.completed: 'completed', + TaskState.canceled: 'canceled', + TaskState.failed: 'failed', + TaskState.rejected: 'rejected', + TaskState.authRequired: 'authRequired', + TaskState.unknown: 'unknown', +}; + +_Artifact _$ArtifactFromJson(Map json) => _Artifact( + artifactId: json['artifactId'] as String, + name: json['name'] as String?, + description: json['description'] as String?, + parts: (json['parts'] as List) + .map((e) => Part.fromJson(e as Map)) + .toList(), + metadata: json['metadata'] as Map?, + extensions: (json['extensions'] as List?) + ?.map((e) => e as String) + .toList(), +); + +Map _$ArtifactToJson(_Artifact instance) => { + 'artifactId': instance.artifactId, + 'name': instance.name, + 'description': instance.description, + 'parts': instance.parts.map((e) => e.toJson()).toList(), + 'metadata': instance.metadata, + 'extensions': instance.extensions, +}; diff --git a/packages/a2a_dart/pubspec.yaml b/packages/a2a_dart/pubspec.yaml new file mode 100644 index 000000000..412f3cd68 --- /dev/null +++ b/packages/a2a_dart/pubspec.yaml @@ -0,0 +1,31 @@ +# Copyright 2025 The Flutter Authors. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +name: a2a_dart +description: A Dart client implementation of the A2A (Agent-to-Agent) protocol. +version: 0.1.0 +publish_to: none +repository: https://github.com/flutter/genui.git +homepage: https://github.com/flutter/genui/tree/main/packages/a2a_dart + +environment: + sdk: '>=3.9.2 <4.0.0' + +dependencies: + freezed_annotation: ^3.1.0 + http: ^1.2.1 + json_annotation: ^4.9.0 + logging: ^1.3.0 + + sse_channel: ^0.2.2 + uuid: ^4.5.2 + +dev_dependencies: + build_runner: ^2.4.9 + dart_flutter_team_lints: ^3.5.2 + freezed: ^3.2.3 + json_serializable: ^6.8.0 + lints: ^6.0.0 + + test: ^1.25.2 diff --git a/packages/a2a_dart/test/client/a2a_client_compliance_test.dart b/packages/a2a_dart/test/client/a2a_client_compliance_test.dart new file mode 100644 index 000000000..6b18142ea --- /dev/null +++ b/packages/a2a_dart/test/client/a2a_client_compliance_test.dart @@ -0,0 +1,108 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:test/test.dart'; + +import '../fakes.dart'; + +void main() { + group('A2AClient Compliance', () { + late A2AClient client; + late FakeTransport transport; + + setUp(() { + transport = FakeTransport(response: {}); + client = A2AClient(url: 'http://example.com', transport: transport); + }); + + test('listTasks sends correct request and parses response', () async { + final params = const ListTasksParams(pageSize: 10); + final result = const ListTasksResult( + tasks: [], + totalSize: 0, + pageSize: 10, + nextPageToken: '', + ); + transport.response['result'] = result.toJson(); + + final response = await client.listTasks(params); + + expect(response.tasks, isEmpty); + expect(response.nextPageToken, isEmpty); + }); + + test('setPushNotificationConfig sends correct request', () async { + final config = const TaskPushNotificationConfig( + taskId: 'task-123', + pushNotificationConfig: PushNotificationConfig( + id: 'config-123', + url: 'http://example.com/push', + ), + ); + transport.response['result'] = config.toJson(); + + await client.setPushNotificationConfig(config); + }); + + test('getPushNotificationConfig sends correct request', () async { + final config = const TaskPushNotificationConfig( + taskId: 'task-123', + pushNotificationConfig: PushNotificationConfig( + id: 'config-123', + url: 'http://example.com/push', + ), + ); + transport.response['result'] = config.toJson(); + + await client.getPushNotificationConfig('task-123', 'config-123'); + }); + + test('listPushNotificationConfigs sends correct request', () async { + transport.response['result'] = {'configs': >[]}; + + final response = await client.listPushNotificationConfigs('task-123'); + + expect(response, isEmpty); + }); + + test('deletePushNotificationConfig sends correct request', () async { + transport.response['result'] = {}; + + await client.deletePushNotificationConfig('task-123', 'config-123'); + }); + + test('authHeaders are passed to transport', () async { + final authHeaders = {'Authorization': 'Bearer test-token'}; + transport = FakeTransport(response: {}, authHeaders: authHeaders); + client = A2AClient(url: 'http://example.com', transport: transport); + + expect(transport.authHeaders, equals(authHeaders)); + }); + + test('correct exception is thrown for generic JSON-RPC error', () { + transport.response['error'] = { + 'code': -32600, + 'message': 'Invalid Request', + }; + + expect( + () => client.getTask('bad-task-id'), + throwsA(isA()), + ); + }); + + test('correct exception is thrown for A2A error codes', () { + transport.response['error'] = { + 'code': -32001, + 'message': 'Task not found', + }; + + expect( + () => client.getTask('bad-task-id'), + throwsA(isA()), + ); + }); + }); +} diff --git a/packages/a2a_dart/test/client/a2a_client_test.dart b/packages/a2a_dart/test/client/a2a_client_test.dart new file mode 100644 index 000000000..c9e8b92fa --- /dev/null +++ b/packages/a2a_dart/test/client/a2a_client_test.dart @@ -0,0 +1,97 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:logging/logging.dart'; +import 'package:test/test.dart'; + +import '../fakes.dart'; + +void main() { + hierarchicalLoggingEnabled = true; + group('A2AClient', () { + late A2AClient client; + + test('getAgentCard returns an AgentCard on success', () async { + final agentCardJson = { + 'protocolVersion': '0.1.0', + 'name': 'Test Agent', + 'description': 'A test agent.', + 'url': 'https://example.com/a2a', + 'version': '1.0.0', + 'capabilities': { + 'streaming': false, + 'pushNotifications': false, + 'stateTransitionHistory': false, + }, + 'defaultInputModes': [], + 'defaultOutputModes': [], + 'skills': [], + }; + final agentCard = AgentCard.fromJson(agentCardJson); + client = A2AClient( + url: 'http://localhost:8080', + transport: FakeTransport(response: agentCardJson), + ); + + final result = await client.getAgentCard(); + + expect(result.name, equals(agentCard.name)); + }); + + test('messageSend returns an Event on success', () async { + final message = const Message( + messageId: '1', + role: Role.user, + parts: [Part.text(text: 'Hello')], + ); + final taskJson = { + 'kind': 'task', + 'id': '123', + 'contextId': '456', + 'status': {'state': 'submitted'}, + }; + + client = A2AClient( + url: 'http://localhost:8080', + transport: FakeTransport(response: {'result': taskJson}), + ); + + final result = await client.messageSend(message); + + expect(result, isA()); + expect(result.id, equals(Task.fromJson(taskJson).id)); + }); + + test('messageStream returns a stream of StreamingEvents on success', () { + final streamController = StreamController>(); + final event = const Event.taskStatusUpdate( + taskId: '123', + contextId: '456', + status: TaskStatus(state: TaskState.working), + final_: false, + ); + + client = A2AClient( + url: 'http://localhost:8080', + transport: FakeTransport(response: {}, stream: streamController.stream), + ); + + final stream = client.messageStream( + const Message( + messageId: '1', + role: Role.user, + parts: [Part.text(text: 'Hello')], + ), + ); + + expect(stream, emitsInOrder([event, emitsDone])); + + streamController.add(event.toJson()); + streamController.close(); + }); + }); +} diff --git a/packages/a2a_dart/test/client/http_transport_test.dart b/packages/a2a_dart/test/client/http_transport_test.dart new file mode 100644 index 000000000..b66553062 --- /dev/null +++ b/packages/a2a_dart/test/client/http_transport_test.dart @@ -0,0 +1,47 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:test/test.dart'; + +import '../fakes.dart'; + +void main() { + group('HttpTransport', () { + test('send returns a Map on success', () async { + final response = { + 'result': {'message': 'success'}, + }; + final transport = HttpTransport( + url: 'http://localhost:8080', + client: FakeHttpClient(response), + ); + + final result = await transport.send({}); + + expect(result, equals(response)); + }); + + test('get returns a Map on success', () async { + final response = {'message': 'success'}; + final transport = HttpTransport( + url: 'http://localhost:8080', + client: FakeHttpClient(response), + ); + + final result = await transport.get('/test'); + + expect(result, equals(response)); + }); + + test('send throws an exception on error', () { + final transport = HttpTransport( + url: 'http://localhost:8080', + client: FakeHttpClient({}, statusCode: 400), + ); + + expect(transport.send({}), throwsException); + }); + }); +} diff --git a/packages/a2a_dart/test/client/sse_transport_test.dart b/packages/a2a_dart/test/client/sse_transport_test.dart new file mode 100644 index 000000000..54fa9ebef --- /dev/null +++ b/packages/a2a_dart/test/client/sse_transport_test.dart @@ -0,0 +1,134 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:http/http.dart' as http; +import 'package:http/testing.dart'; +import 'package:test/test.dart'; + +void main() { + group('SseTransport', () { + test('handles multi-line data', () async { + final mockHttp = MockClient((request) async { + final stream = Stream.fromIterable( + [ + 'data: { "result": { "line1": "hello",\n', + 'data: "line2": "world" } }\n\n', + ].map((e) => utf8.encode(e)), + ); + final bytes = (await stream.toList()).expand((i) => i).toList(); + return http.Response.bytes(bytes, 200); + }); + final transport = SseTransport( + url: 'http://localhost:8080', + client: mockHttp, + ); + final stream = transport.sendStream({}); + expect( + stream, + emitsInOrder([ + {'line1': 'hello', 'line2': 'world'}, + emitsDone, + ]), + ); + }); + + test('handles comments', () async { + final mockHttp = MockClient((request) async { + final stream = Stream.fromIterable( + [ + ': this is a comment\n', + 'data: { "result": { "key": "value" } }\n\n', + ].map((e) => utf8.encode(e)), + ); + final bytes = (await stream.toList()).expand((i) => i).toList(); + return http.Response.bytes(bytes, 200); + }); + final transport = SseTransport( + url: 'http://localhost:8080', + client: mockHttp, + ); + final stream = transport.sendStream({}); + expect( + stream, + emitsInOrder([ + {'key': 'value'}, + emitsDone, + ]), + ); + }); + + test('handles parsing errors', () async { + final mockHttp = MockClient((request) async { + final stream = Stream.fromIterable( + [ + 'data: { "result": { "key": "value" } }\n\n', + 'data: { "error": { "code": -32000, ' + '"message": "Server error" } }\n\n', + ].map((e) => utf8.encode(e)), + ); + final bytes = (await stream.toList()).expand((i) => i).toList(); + return http.Response.bytes(bytes, 200); + }); + final transport = SseTransport( + url: 'http://localhost:8080', + client: mockHttp, + ); + final stream = transport.sendStream({}); + expect( + stream, + emitsInOrder([ + {'key': 'value'}, + emitsError(isA()), + emitsDone, + ]), + ); + }); + + test('handles http errors', () async { + final mockHttp = MockClient.streaming((request, body) async { + return http.StreamedResponse( + Stream.value([]), + 400, + reasonPhrase: 'Bad Request', + ); + }); + final transport = SseTransport( + url: 'http://localhost:8080', + client: mockHttp, + ); + final stream = transport.sendStream({}); + expect(stream, emitsError(isA())); + }); + + test('handles parsing errors', () async { + final mockHttp = MockClient((request) async { + final stream = Stream.fromIterable( + [ + 'data: { "result": { "key": "value" } }\n\n', + 'data: not json\n\n', + ].map((e) => utf8.encode(e)), + ); + final bytes = (await stream.toList()).expand((i) => i).toList(); + return http.Response.bytes(bytes, 200); + }); + final transport = SseTransport( + url: 'http://localhost:8080', + client: mockHttp, + ); + final stream = transport.sendStream({}); + expect( + stream, + emitsInOrder([ + {'key': 'value'}, + emitsError(isA()), + emitsDone, + ]), + ); + }); + }); +} diff --git a/packages/a2a_dart/test/core/agent_card_test.dart b/packages/a2a_dart/test/core/agent_card_test.dart new file mode 100644 index 000000000..6b15641e9 --- /dev/null +++ b/packages/a2a_dart/test/core/agent_card_test.dart @@ -0,0 +1,148 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:test/test.dart'; + +void main() { + group('AgentCard', () { + test('can be instantiated', () { + final agentCard = const AgentCard( + protocolVersion: '0.2.9', + name: 'Test Agent', + description: 'A test agent.', + url: 'https://example.com/a2a', + version: '1.0.0', + capabilities: AgentCapabilities(), + defaultInputModes: [], + defaultOutputModes: [], + skills: [], + ); + expect(agentCard, isNotNull); + }); + + test('can be serialized and deserialized from JSON', () { + final json = jsonDecode(agentCardJson) as Map; + final agentCard = AgentCard.fromJson(json); + final serializedJson = agentCard.toJson(); + final agentCard2 = AgentCard.fromJson(serializedJson); + expect(agentCard2, equals(agentCard)); + expect(agentCard.name, equals('GeoSpatial Route Planner Agent')); + expect(agentCard.skills.length, equals(2)); + }); + }); +} + +const agentCardJson = ''' +{ + "protocolVersion": "0.2.9", + "name": "GeoSpatial Route Planner Agent", + "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", + "url": "https://georoute-agent.example.com/a2a/v1", + "preferredTransport": "JSONRPC", + "additionalInterfaces": [ + { + "url": "https://georoute-agent.example.com/a2a/v1", + "transport": "JSONRPC" + }, + { + "url": "https://georoute-agent.example.com/a2a/grpc", + "transport": "GRPC" + }, + { + "url": "https://georoute-agent.example.com/a2a/json", + "transport": "HTTP+JSON" + } + ], + "provider": { + "organization": "Example Geo Services Inc.", + "url": "https://www.examplegeoservices.com" + }, + "iconUrl": "https://georoute-agent.example.com/icon.png", + "version": "1.2.0", + "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", + "capabilities": { + "streaming": true, + "pushNotifications": true, + "stateTransitionHistory": false + }, + "securitySchemes": { + "google": { + "type": "openIdConnect", + "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" + } + }, + "security": [ + { + "google": [ + "openid", + "profile", + "email" + ] + } + ], + "defaultInputModes": [ + "application/json", + "text/plain" + ], + "defaultOutputModes": [ + "application/json", + "image/png" + ], + "skills": [ + { + "id": "route-optimizer-traffic", + "name": "Traffic-Aware Route Optimizer", + "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", + "tags": [ + "maps", + "routing", + "navigation", + "directions", + "traffic" + ], + "examples": [ + "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", + "{\\"origin\\": {\\"lat\\": 37.422, \\"lng\\": -122.084}, \\"destination\\": {\\"lat\\": 37.7749, \\"lng\\": -122.4194}, \\"preferences\\": [\\"avoid_ferries\\"]}" + ], + "inputModes": [ + "application/json", + "text/plain" + ], + "outputModes": [ + "application/json", + "application/vnd.geo+json", + "text/html" + ] + }, + { + "id": "custom-map-generator", + "name": "Personalized Map Generator", + "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", + "tags": [ + "maps", + "customization", + "visualization", + "cartography" + ], + "examples": [ + "Generate a map of my upcoming road trip with all planned stops highlighted.", + "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." + ], + "inputModes": [ + "application/json" + ], + "outputModes": [ + "image/png", + "image/jpeg", + "application/json", + "text/html" + ] + } + ], + "supportsAuthenticatedExtendedCard": true +} +'''; diff --git a/packages/a2a_dart/test/core/data_models_test.dart b/packages/a2a_dart/test/core/data_models_test.dart new file mode 100644 index 000000000..2c3c991f1 --- /dev/null +++ b/packages/a2a_dart/test/core/data_models_test.dart @@ -0,0 +1,210 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:test/test.dart'; + +void main() { + group('Data Models', () { + test('AgentCard can be serialized and deserialized', () { + final agentCard = const AgentCard( + protocolVersion: '1.0', + name: 'Test Agent', + description: 'An agent for testing', + url: 'https://example.com/agent', + version: '1.0.0', + capabilities: AgentCapabilities(), + defaultInputModes: ['text'], + defaultOutputModes: ['text'], + skills: [], + ); + + final json = agentCard.toJson(); + final newAgentCard = AgentCard.fromJson(json); + + expect(newAgentCard, equals(agentCard)); + expect(newAgentCard.name, equals('Test Agent')); + }); + + test('AgentCard with optional fields null can be serialized and ' + 'deserialized', () { + final agentCard = const AgentCard( + protocolVersion: '1.0', + name: 'Test Agent', + description: 'An agent for testing', + url: 'https://example.com/agent', + version: '1.0.0', + capabilities: AgentCapabilities(), + defaultInputModes: [], + defaultOutputModes: [], + skills: [], + ); + + final json = agentCard.toJson(); + final newAgentCard = AgentCard.fromJson(json); + + expect(newAgentCard, equals(agentCard)); + }); + + test('Message can be serialized and deserialized', () { + final message = const Message( + role: Role.user, + parts: [Part.text(text: 'Hello, agent!')], + messageId: '12345', + ); + + final json = message.toJson(); + final newMessage = Message.fromJson(json); + + expect(newMessage, equals(message)); + expect(newMessage.role, equals(Role.user)); + }); + + test('Message with empty parts can be serialized and deserialized', () { + final message = const Message( + role: Role.user, + parts: [], + messageId: '12345', + ); + + final json = message.toJson(); + final newMessage = Message.fromJson(json); + + expect(newMessage, equals(message)); + }); + + test('Message with multiple parts can be serialized and deserialized', () { + final message = const Message( + role: Role.user, + parts: [ + Part.text(text: 'Hello'), + Part.file( + file: FileType.uri( + uri: 'file:///path/to/file.txt', + mimeType: 'text/plain', + ), + ), + Part.data(data: {'key': 'value'}), + ], + messageId: '12345', + ); + + final json = message.toJson(); + final newMessage = Message.fromJson(json); + + expect(newMessage, equals(message)); + }); + + test('Task can be serialized and deserialized', () { + final task = const Task( + id: 'task-123', + contextId: 'context-456', + status: TaskStatus(state: TaskState.working), + artifacts: [ + Artifact( + artifactId: 'artifact-1', + parts: [Part.text(text: 'Hello')], + ), + ], + ); + + final json = task.toJson(); + final newTask = Task.fromJson(json); + + expect(newTask, equals(task)); + expect(newTask.id, equals('task-123')); + }); + + test( + 'Task with optional fields null can be serialized and deserialized', + () { + final task = const Task( + id: 'task-123', + contextId: 'context-456', + status: TaskStatus(state: TaskState.working), + ); + + final json = task.toJson(); + final newTask = Task.fromJson(json); + + expect(newTask, equals(task)); + }, + ); + + test('Part can be serialized and deserialized', () { + final partText = const Part.text(text: 'Hello'); + final jsonText = partText.toJson(); + final newPartText = Part.fromJson(jsonText); + expect(newPartText, equals(partText)); + + final partFileUri = const Part.file( + file: FileType.uri( + uri: 'file:///path/to/file.txt', + mimeType: 'text/plain', + ), + ); + final jsonFileUri = partFileUri.toJson(); + final newPartFileUri = Part.fromJson(jsonFileUri); + expect(newPartFileUri, equals(partFileUri)); + + final partFileBytes = const Part.file( + file: FileType.bytes( + bytes: 'aGVsbG8=', // base64 for "hello" + name: 'hello.txt', + ), + ); + final jsonFileBytes = partFileBytes.toJson(); + final newPartFileBytes = Part.fromJson(jsonFileBytes); + expect(newPartFileBytes, equals(partFileBytes)); + + final partData = const Part.data(data: {'key': 'value'}); + final jsonData = partData.toJson(); + final newPartData = Part.fromJson(jsonData); + expect(newPartData, equals(partData)); + }); + + test('SecurityScheme can be serialized and deserialized', () { + final securityScheme = const SecurityScheme.apiKey( + name: 'test_key', + in_: 'header', + ); + + final json = securityScheme.toJson(); + final newSecurityScheme = SecurityScheme.fromJson(json); + + expect(newSecurityScheme, equals(securityScheme)); + }); + + test('PushNotificationConfig can be serialized and deserialized', () { + final config = const PushNotificationConfig( + id: 'config-1', + url: 'https://example.com/push', + authentication: PushNotificationAuthenticationInfo( + schemes: ['Bearer'], + credentials: 'test-token', + ), + ); + + final json = config.toJson(); + final newConfig = PushNotificationConfig.fromJson(json); + + expect(newConfig, equals(config)); + }); + + test('TaskPushNotificationConfig can be serialized and deserialized', () { + final taskConfig = const TaskPushNotificationConfig( + taskId: 'task-123', + pushNotificationConfig: PushNotificationConfig( + id: 'config-1', + url: 'https://example.com/push', + ), + ); + + final json = taskConfig.toJson(); + final newTaskConfig = TaskPushNotificationConfig.fromJson(json); + + expect(newTaskConfig, equals(taskConfig)); + }); + }); +} diff --git a/packages/a2a_dart/test/example_test.dart b/packages/a2a_dart/test/example_test.dart new file mode 100644 index 000000000..f8f5cbdd9 --- /dev/null +++ b/packages/a2a_dart/test/example_test.dart @@ -0,0 +1,104 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:a2a_dart/a2a_dart.dart'; +import 'package:test/test.dart'; +import 'package:uuid/uuid.dart'; + +import 'fake_transport.dart'; + +void main() { + test('example client and server', () async { + final transport = FakeTransport(); + final client = A2AClient(url: 'http://localhost/', transport: transport); + addTearDown(client.close); + + final message = Message( + messageId: const Uuid().v4(), + role: Role.user, + parts: const [Part.text(text: 'start 10')], + ); + final stream = client.messageStream(message); + String? taskId; + final events = []; + + final completer = Completer(); + + stream.listen((event) { + taskId ??= event.taskId; + if (event is TaskArtifactUpdate) { + for (final part in event.artifact.parts) { + if (part is TextPart) { + events.add(part.text); + if (part.text.contains('Countdown at 5')) { + unawaited( + client.messageSend( + Message( + messageId: const Uuid().v4(), + role: Role.user, + parts: const [Part.text(text: 'pause')], + taskId: taskId, + ), + ), + ); + } + } + } + } + }, onDone: completer.complete); + + transport.addEvent( + const Event.taskStatusUpdate( + taskId: 'task-123', + contextId: 'context-123', + status: TaskStatus(state: TaskState.working), + final_: false, + ), + ); + + for (var i = 10; i >= 0; i--) { + transport.addEvent( + Event.taskArtifactUpdate( + taskId: 'task-123', + contextId: 'context-123', + artifact: Artifact( + artifactId: 'artifact-$i', + parts: [Part.text(text: 'Countdown at $i!')], + ), + append: false, + lastChunk: i == 0, + ), + ); + await Future.delayed(const Duration(milliseconds: 10)); + } + transport.addEvent( + const Event.taskStatusUpdate( + taskId: 'task-123', + contextId: 'context-123', + status: TaskStatus(state: TaskState.completed), + final_: true, + ), + ); + transport.addEvent( + const Event.taskArtifactUpdate( + taskId: 'task-123', + contextId: 'context-123', + artifact: Artifact( + artifactId: 'artifact-liftoff', + parts: [Part.text(text: 'Liftoff!')], + ), + append: false, + lastChunk: true, + ), + ); + transport.close(); + + await completer.future; + + expect(events.join('\n'), contains('Countdown at 5')); + expect(events.join('\n'), contains('Liftoff!')); + }); +} diff --git a/packages/a2a_dart/test/fake_transport.dart b/packages/a2a_dart/test/fake_transport.dart new file mode 100644 index 000000000..c48a8f41d --- /dev/null +++ b/packages/a2a_dart/test/fake_transport.dart @@ -0,0 +1,59 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:a2a_dart/a2a_dart.dart'; + +class FakeTransport implements Transport { + @override + Map authHeaders; + + final _requests = >[]; + final _streamRequests = >[]; + final _streamController = StreamController>(); + + List> get requests => _requests; + List> get streamRequests => _streamRequests; + + FakeTransport({this.authHeaders = const {}}); + + @override + Future> send( + Map request, { + String path = 'rpc', + }) async { + _requests.add(request); + return Future.value({ + 'result': const Task( + id: 'task-123', + contextId: 'context-123', + status: TaskStatus(state: TaskState.working), + ).toJson(), + }); + } + + @override + Stream> sendStream(Map request) { + _streamRequests.add(request); + return _streamController.stream; + } + + void addEvent(Event event) { + _streamController.add(event.toJson()); + } + + @override + void close() { + _streamController.close(); + } + + @override + Future> get( + String path, { + Map? headers, + }) { + throw UnimplementedError(); + } +} diff --git a/packages/a2a_dart/test/fakes.dart b/packages/a2a_dart/test/fakes.dart new file mode 100644 index 000000000..76ca7d68b --- /dev/null +++ b/packages/a2a_dart/test/fakes.dart @@ -0,0 +1,72 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'package:a2a_dart/a2a_dart.dart'; + +import 'package:http/http.dart' as http; + +class FakeHttpClient implements http.Client { + final Map response; + final int statusCode; + + FakeHttpClient(this.response, {this.statusCode = 200}); + + @override + Future get(Uri url, {Map? headers}) async { + return http.Response(jsonEncode(response), statusCode); + } + + @override + Future post( + Uri url, { + Map? headers, + Object? body, + Encoding? encoding, + }) async { + return http.Response(jsonEncode(response), statusCode); + } + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +class FakeTransport implements Transport { + @override + Map authHeaders; + + final Map response; + final Stream> stream; + + FakeTransport({ + required this.response, + Stream>? stream, + this.authHeaders = const {}, + }) : stream = stream ?? Stream.value(response); + + @override + Future> get( + String path, { + Map headers = const {}, + }) async { + return response; + } + + @override + Future> send( + Map request, { + String path = '', + }) async { + return response; + } + + @override + Stream> sendStream(Map request) { + return stream; + } + + @override + void close() {} +} diff --git a/tool/jules_setup.sh b/tool/jules_setup.sh old mode 100644 new mode 100755 diff --git a/tool/test_and_fix/GEMINI.md b/tool/test_and_fix/GEMINI.md index c0bdc22d3..676c3f4ef 100644 --- a/tool/test_and_fix/GEMINI.md +++ b/tool/test_and_fix/GEMINI.md @@ -4,6 +4,8 @@ The `test_and_fix` package is a command-line tool designed to automate the process of running tests, analysis, and code formatting across all Dart and Flutter projects within the `genui` monorepo. It replaces the functionality of the original `run_all_tests_and_fixes.sh` script with a more robust and platform-independent Dart solution. +It is not meant to be used to run specific tests, but rather as something that is run right before committing code to ensure that the code is in a good state. + ## Implementation Details The tool is architected with a separation of concerns: the command-line argument parsing and the core logic.