use serde::{Deserialize, Serialize};
use crate::message::Message;
use crate::push::TaskPushNotificationConfig;
use crate::task::TaskState;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SendMessageConfiguration {
pub accepted_output_modes: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub task_push_notification_config: Option<TaskPushNotificationConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub history_length: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub return_immediately: Option<bool>,
}
impl Default for SendMessageConfiguration {
fn default() -> Self {
Self {
accepted_output_modes: vec!["text/plain".to_owned()],
task_push_notification_config: None,
history_length: None,
return_immediately: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MessageSendParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
pub message: Message,
#[serde(skip_serializing_if = "Option::is_none")]
pub configuration: Option<SendMessageConfiguration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TaskQueryParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub history_length: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TaskIdParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CancelTaskParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListTasksParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub context_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<TaskState>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status_timestamp_after: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub include_artifacts: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub history_length: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetPushConfigParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
pub task_id: String,
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DeletePushConfigParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
pub task_id: String,
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListPushConfigsParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
pub task_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_size: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub page_token: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetExtendedAgentCardParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::message::{MessageId, MessageRole, Part};
fn make_message() -> Message {
Message {
id: MessageId::new("msg-1"),
role: MessageRole::User,
parts: vec![Part::text("hello")],
task_id: None,
context_id: None,
reference_task_ids: None,
extensions: None,
metadata: None,
}
}
#[test]
fn message_send_params_roundtrip() {
let params = MessageSendParams {
tenant: None,
message: make_message(),
configuration: Some(SendMessageConfiguration {
accepted_output_modes: vec!["text/plain".into()],
task_push_notification_config: None,
history_length: Some(10),
return_immediately: None,
}),
metadata: None,
};
let json = serde_json::to_string(¶ms).expect("serialize");
let back: MessageSendParams = serde_json::from_str(&json).expect("deserialize");
assert_eq!(back.message.id, MessageId::new("msg-1"));
}
#[test]
fn list_tasks_params_empty_roundtrip() {
let params = ListTasksParams {
tenant: None,
context_id: None,
status: None,
page_size: None,
page_token: None,
status_timestamp_after: None,
include_artifacts: None,
history_length: None,
};
let json = serde_json::to_string(¶ms).expect("serialize");
assert_eq!(json, "{}", "empty params should serialize to {{}}");
}
#[test]
fn task_query_params_roundtrip() {
let params = TaskQueryParams {
tenant: None,
id: "task-1".into(),
history_length: Some(5),
};
let json = serde_json::to_string(¶ms).expect("serialize");
let back: TaskQueryParams = serde_json::from_str(&json).expect("deserialize");
assert_eq!(back.id, "task-1");
assert_eq!(back.history_length, Some(5));
}
#[test]
fn cancel_task_params_roundtrip() {
let params = CancelTaskParams {
tenant: Some("my-tenant".into()),
id: "task-1".into(),
metadata: Some(serde_json::json!({"reason": "no longer needed"})),
};
let json = serde_json::to_string(¶ms).expect("serialize");
let back: CancelTaskParams = serde_json::from_str(&json).expect("deserialize");
assert_eq!(back.id, "task-1");
assert_eq!(back.tenant.as_deref(), Some("my-tenant"));
assert!(back.metadata.is_some());
}
#[test]
fn wire_format_list_tasks_history_length() {
let params = ListTasksParams {
tenant: None,
context_id: None,
status: None,
page_size: None,
page_token: None,
status_timestamp_after: None,
include_artifacts: None,
history_length: Some(10),
};
let json = serde_json::to_string(¶ms).unwrap();
assert!(
json.contains("\"historyLength\":10"),
"historyLength must appear: {json}"
);
let back: ListTasksParams = serde_json::from_str(&json).unwrap();
assert_eq!(back.history_length, Some(10));
}
#[test]
fn wire_format_list_push_configs_params() {
let params = super::ListPushConfigsParams {
tenant: None,
task_id: "t1".into(),
page_size: Some(20),
page_token: None,
};
let json = serde_json::to_string(¶ms).unwrap();
assert!(json.contains("\"taskId\":\"t1\""));
assert!(json.contains("\"pageSize\":20"));
}
}