Skip to main content

systemprompt_models/a2a/
message.rs

1use serde::{Deserialize, Serialize};
2use systemprompt_identifiers::{ContextId, MessageId, TaskId};
3
4#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
5#[serde(rename_all = "camelCase")]
6#[allow(clippy::struct_field_names)]
7pub struct Message {
8    pub role: MessageRole,
9    pub parts: Vec<Part>,
10    pub message_id: MessageId,
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub task_id: Option<TaskId>,
13    pub context_id: ContextId,
14    pub metadata: Option<serde_json::Value>,
15    pub extensions: Option<Vec<String>>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub reference_task_ids: Option<Vec<TaskId>>,
18}
19
20#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
21pub enum MessageRole {
22    #[serde(rename = "ROLE_USER")]
23    User,
24    #[serde(rename = "ROLE_AGENT")]
25    Agent,
26}
27
28#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
29#[serde(untagged)]
30pub enum Part {
31    Text(TextPart),
32    File(FilePart),
33    Data(DataPart),
34}
35
36#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
37pub struct TextPart {
38    pub text: String,
39}
40
41#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
42pub struct DataPart {
43    pub data: serde_json::Map<String, serde_json::Value>,
44}
45
46#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
47pub struct FilePart {
48    pub file: FileContent,
49}
50
51#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
52#[serde(rename_all = "camelCase")]
53pub struct FileContent {
54    pub name: Option<String>,
55    pub mime_type: Option<String>,
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub bytes: Option<String>,
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub url: Option<String>,
60}
61
62impl Part {
63    pub fn as_text(&self) -> Option<&str> {
64        match self {
65            Self::Text(text_part) => Some(&text_part.text),
66            _ => None,
67        }
68    }
69
70    pub fn as_data(&self) -> Option<serde_json::Value> {
71        match self {
72            Self::Data(data_part) => Some(serde_json::Value::Object(data_part.data.clone())),
73            _ => None,
74        }
75    }
76
77    pub fn as_file(&self) -> Option<serde_json::Value> {
78        match self {
79            Self::File(file_part) => serde_json::to_value(&file_part.file).ok(),
80            _ => None,
81        }
82    }
83}