uarp-sdk 0.5.7

Async Rust client for the UARP (Snaga) Universal Agent Runtime Platform API
Documentation
// Code generated by @uarp/codegen from spec/openapi.json. DO NOT EDIT.
//!
//! Agent-to-Agent protocol: discovery and task execution

#![allow(unused_imports, clippy::too_many_arguments)]

use reqwest::Method;
use serde::{Deserialize, Serialize};
use futures_core::Stream;

use crate::client::{Client, Request, NO_BODY, NO_QUERY};
use crate::error::Result;
use crate::generated::models;
use crate::multipart::{field_text, FilePart};
use crate::pagination::CursorGuard;
use crate::sse::EventStream;
use crate::util::encode_path;

/// Query and header parameters for `getAgentCard`.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct GetAgentCardParams {
    pub agent_id: String,
}

/// Query and header parameters for `listA2ATasks`.
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct ListA2ATasksParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub limit: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub cursor: Option<String>,
}

/// Agent-to-Agent protocol: discovery and task execution
#[derive(Debug, Clone)]
pub struct A2AApi {
    pub(crate) client: Client,
}

impl Client {
    /// Agent-to-Agent protocol: discovery and task execution
    pub fn a2a(&self) -> A2AApi {
        A2AApi { client: self.clone() }
    }
}

impl A2AApi {
    /// A2A JSON-RPC 2.0 endpoint
    ///
    /// Handles `tasks/send`, `tasks/sendSubscribe`, `tasks/get`, `tasks/cancel`,
    /// `tasks/pushNotification/set`, `tasks/pushNotification/get` via JSON-RPC 2.0.
    ///
    /// **Scope dispatch is dynamic per JSON-RPC method**: read-style methods (`tasks/get`,
    /// `tasks/pushNotification/get`) require `agents:read`; write-style (`tasks/send`,
    /// `tasks/sendSubscribe`, `tasks/cancel`, `tasks/pushNotification/set`) require `agents:write`.
    /// The static `bearerAuth: \[agents:write\]` declared here is the *strictest* scope; an
    /// `agents:read`-only key works for the read methods but the spec cannot express the per-method
    /// conditional.
    ///
    /// `POST /api/v1/a2a`
    ///
    /// Required scopes: `agents:write`.
    pub async fn a2a_json_rpc(&self, body: &models::A2ajsonRpcRequest) -> Result<serde_json::Value> {
        self.client
            .request_json(Request {
                method: Method::POST,
                path: "/api/v1/a2a".to_string(),
                query: NO_QUERY,
                body: Some(body),
                headers: Vec::new(),
                idempotent: true,
            })
            .await
    }

    /// Cancel an A2A task
    ///
    /// `POST /api/v1/a2a/tasks/{taskId}/cancel`
    ///
    /// Required scopes: `agents:write`.
    pub async fn cancel_a2a_task(&self, task_id: &str) -> Result<serde_json::Value> {
        self.client
            .request_json(Request {
                method: Method::POST,
                path: format!("/api/v1/a2a/tasks/{}/cancel", encode_path(task_id)),
                query: NO_QUERY,
                body: NO_BODY,
                headers: Vec::new(),
                idempotent: true,
            })
            .await
    }

    /// Create an A2A task
    ///
    /// Creates a new agent-to-agent task and schedules the underlying run.
    ///
    /// `POST /api/v1/a2a/tasks`
    ///
    /// Required scopes: `agents:write`.
    pub async fn create_a2a_task(&self, body: &models::CreateA2ATaskRequest) -> Result<serde_json::Value> {
        self.client
            .request_json(Request {
                method: Method::POST,
                path: "/api/v1/a2a/tasks".to_string(),
                query: NO_QUERY,
                body: Some(body),
                headers: Vec::new(),
                idempotent: true,
            })
            .await
    }

    /// Get A2A task status
    ///
    /// `GET /api/v1/a2a/tasks/{taskId}`
    ///
    /// Required scopes: `agents:read`.
    pub async fn get_a2a_task(&self, task_id: &str) -> Result<serde_json::Value> {
        self.client
            .request_json(Request {
                method: Method::GET,
                path: format!("/api/v1/a2a/tasks/{}", encode_path(task_id)),
                query: NO_QUERY,
                body: NO_BODY,
                headers: Vec::new(),
                idempotent: false,
            })
            .await
    }

    /// Get A2A agent card for discovery
    ///
    /// `GET /.well-known/agent.json`
    pub async fn get_agent_card(&self, params: &GetAgentCardParams) -> Result<serde_json::Value> {
        self.client
            .request_json(Request {
                method: Method::GET,
                path: "/.well-known/agent.json".to_string(),
                query: Some(params),
                body: NO_BODY,
                headers: Vec::new(),
                idempotent: false,
            })
            .await
    }

    /// List A2A tasks
    ///
    /// `GET /api/v1/a2a/tasks`
    ///
    /// Required scopes: `agents:read`.
    pub async fn list_a2a_tasks(&self, params: &ListA2ATasksParams) -> Result<models::ListA2ATasksResponse> {
        self.client
            .request_json(Request {
                method: Method::GET,
                path: "/api/v1/a2a/tasks".to_string(),
                query: Some(params),
                body: NO_BODY,
                headers: Vec::new(),
                idempotent: false,
            })
            .await
    }

    /// Stream every item returned by `listA2ATasks`, following the `cursor` cursor until the server
    /// reports no further pages.
    pub fn list_a2a_tasks_all<'a>(&'a self, params: &'a ListA2ATasksParams) -> impl Stream<Item = Result<models::A2ATask>> + 'a {
        async_stream::try_stream! {
            let mut guard = CursorGuard::new();
            let mut cursor = params.cursor.clone();
            loop {
                let mut page_params = params.clone();
                page_params.cursor = cursor.clone();
                let page = self.list_a2a_tasks(&page_params).await?;
                let items = page.tasks;
                let was_empty = items.is_empty();
                for item in items {
                    yield item;
                }
                match guard.advance(page.cursor, page.has_more, was_empty) {
                    Some(next) => cursor = Some(next),
                    None => break,
                }
            }
        }
    }

    /// Stream A2A task status updates (SSE)
    ///
    /// `GET /api/v1/a2a/tasks/{taskId}/events`
    ///
    /// Required scopes: `agents:read`.
    ///
    /// Returns a server-sent event stream.
    pub fn stream_a2a_task_events(&self, task_id: &str) -> EventStream {
        self.client.request_stream(
            &format!("/api/v1/a2a/tasks/{}/events", encode_path(task_id)),
            NO_QUERY,
            Vec::new(),
        )
    }
}