conversation_api/
content.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5#[serde(tag = "kind", rename_all = "snake_case")]
6pub enum MediaSource {
7 Artifact { uri: String },
8}
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
11#[serde(tag = "type", rename_all = "snake_case")]
12pub enum MessagePart {
13 Text {
14 text: String,
15 },
16 Image {
17 source: MediaSource,
18 #[serde(default, skip_serializing_if = "Option::is_none")]
19 mime_type: Option<String>,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 alt_text: Option<String>,
22 #[serde(default, skip_serializing_if = "Option::is_none")]
23 detail: Option<String>,
24 },
25 Audio {
26 source: MediaSource,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 mime_type: Option<String>,
29 #[serde(default, skip_serializing_if = "Option::is_none")]
30 transcript: Option<String>,
31 },
32 File {
33 source: MediaSource,
34 #[serde(default, skip_serializing_if = "Option::is_none")]
35 mime_type: Option<String>,
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 name: Option<String>,
38 },
39 Json {
40 value: Value,
41 },
42}
43
44#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
45#[serde(rename_all = "camelCase")]
46pub struct MessageContent {
47 #[serde(default)]
48 pub parts: Vec<MessagePart>,
49}
50
51impl MessageContent {
52 pub fn text(text: impl Into<String>) -> Self {
53 Self {
54 parts: vec![MessagePart::Text { text: text.into() }],
55 }
56 }
57
58 pub fn plain_text(&self) -> String {
59 self.parts
60 .iter()
61 .filter_map(|part| match part {
62 MessagePart::Text { text } => Some(text.as_str()),
63 _ => None,
64 })
65 .collect::<Vec<_>>()
66 .join("\n")
67 }
68
69 pub fn has_non_text_parts(&self) -> bool {
70 self.parts
71 .iter()
72 .any(|part| !matches!(part, MessagePart::Text { .. }))
73 }
74}
75
76#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
77#[serde(rename_all = "snake_case")]
78pub enum ConversationMessageRole {
79 User,
80 Assistant,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
84#[serde(rename_all = "camelCase")]
85pub struct ConversationMessage {
86 pub message_id: String,
87 pub request_id: String,
88 pub role: ConversationMessageRole,
89 pub content: MessageContent,
90 pub created_at: String,
91}