use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AgentCapabilities {
#[serde(default)]
pub streaming: bool,
#[serde(default)]
pub push_notifications: bool,
#[serde(default)]
pub state_transition_history: bool,
}
impl Default for AgentCapabilities {
fn default() -> Self {
Self { streaming: true, push_notifications: false, state_transition_history: false }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentSkill {
pub id: String,
pub name: String,
pub description: String,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub examples: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AgentCard {
pub name: String,
pub description: String,
pub url: String,
#[serde(default = "AgentCard::default_version")]
pub version: String,
#[serde(default = "AgentCard::default_input_modes")]
pub default_input_modes: Vec<String>,
#[serde(default = "AgentCard::default_output_modes")]
pub default_output_modes: Vec<String>,
pub capabilities: AgentCapabilities,
#[serde(default)]
pub skills: Vec<AgentSkill>,
pub security: Option<Vec<HashMap<String, Vec<String>>>>,
pub security_schemes: Option<HashMap<String, serde_json::Value>>,
}
impl AgentCard {
fn default_version() -> String { "1.0.0".to_string() }
fn default_input_modes() -> Vec<String> { vec!["text".to_string(), "text/plain".to_string()] }
fn default_output_modes() -> Vec<String> { vec!["text".to_string(), "text/plain".to_string()] }
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum Part {
Text {
text: String,
#[serde(skip_serializing_if = "Option::is_none")]
metadata: Option<serde_json::Value>,
},
File {
file: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
metadata: Option<serde_json::Value>,
},
Data {
data: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
metadata: Option<serde_json::Value>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum Role {
User,
Agent,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Message {
#[serde(default = "Message::kind_value")]
pub kind: String,
pub message_id: String,
pub role: Role,
pub parts: Vec<Part>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub task_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
impl Message {
fn kind_value() -> String { "message".to_string() }
pub fn user(text: impl Into<String>) -> Self {
Self {
kind: "message".to_string(),
role: Role::User,
parts: vec![Part::Text { text: text.into(), metadata: None }],
message_id: Uuid::new_v4().to_string(),
context_id: None,
task_id: None,
metadata: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum TaskState {
Submitted,
Working,
Completed,
Canceled,
Failed,
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Artifact {
pub artifact_id: String,
pub parts: Vec<Part>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Task {
pub id: String,
pub context_id: String,
pub state: TaskState,
pub artifacts: Vec<Artifact>,
pub history: Vec<Message>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TaskStatus {
pub state: TaskState,
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<Message>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TaskArtifactUpdateEvent {
#[serde(default = "TaskArtifactUpdateEvent::kind_value")]
pub kind: String,
pub task_id: String,
pub context_id: String,
pub artifact: Artifact,
#[serde(skip_serializing_if = "Option::is_none")]
pub append: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_chunk: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
impl TaskArtifactUpdateEvent {
fn kind_value() -> String { "artifact-update".to_string() }
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TaskStatusUpdateEvent {
#[serde(default = "TaskStatusUpdateEvent::kind_value")]
pub kind: String,
pub task_id: String,
pub context_id: String,
pub status: TaskStatus,
pub r#final: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
impl TaskStatusUpdateEvent {
fn kind_value() -> String { "status-update".to_string() }
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonRpcRequest {
pub jsonrpc: String,
pub method: String,
pub id: Option<serde_json::Value>,
pub params: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonRpcResponse<T> {
pub jsonrpc: String,
pub id: Option<serde_json::Value>,
pub result: T,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonRpcError {
pub code: i32,
pub message: String,
pub data: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JsonRpcErrorResponse {
pub jsonrpc: String,
pub id: Option<serde_json::Value>,
pub error: JsonRpcError,
}