vtcode_core/open_responses/
content.rs1use serde::{Deserialize, Serialize};
8
9pub type ContentPartId = String;
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(tag = "type", rename_all = "snake_case")]
18pub enum ContentPart {
19 OutputText(OutputTextContent),
21
22 InputText(InputTextContent),
24
25 InputImage(InputImageContent),
27
28 InputFile(InputFileContent),
30
31 UrlCitation(UrlCitationContent),
33
34 Refusal(RefusalContent),
36}
37
38impl ContentPart {
39 pub fn output_text(text: impl Into<String>) -> Self {
41 Self::OutputText(OutputTextContent { text: text.into() })
42 }
43
44 pub fn input_text(text: impl Into<String>) -> Self {
46 Self::InputText(InputTextContent { text: text.into() })
47 }
48
49 pub fn refusal(refusal: impl Into<String>) -> Self {
51 Self::Refusal(RefusalContent {
52 refusal: refusal.into(),
53 })
54 }
55
56 pub fn as_text(&self) -> Option<&str> {
58 match self {
59 Self::OutputText(c) => Some(&c.text),
60 Self::InputText(c) => Some(&c.text),
61 Self::Refusal(c) => Some(&c.refusal),
62 _ => None,
63 }
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
69pub struct OutputTextContent {
70 pub text: String,
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
76pub struct InputTextContent {
77 pub text: String,
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
83pub struct InputImageContent {
84 pub image_url: String,
86
87 #[serde(default, skip_serializing_if = "Option::is_none")]
89 pub detail: Option<ImageDetail>,
90}
91
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
94#[serde(rename_all = "lowercase")]
95pub enum ImageDetail {
96 Low,
98 High,
100 #[default]
102 Auto,
103 Original,
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
109pub struct InputFileContent {
110 #[serde(skip_serializing_if = "Option::is_none")]
112 pub filename: Option<String>,
113
114 #[serde(skip_serializing_if = "Option::is_none")]
116 pub file_id: Option<String>,
117
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub file_data: Option<String>,
121
122 #[serde(skip_serializing_if = "Option::is_none")]
124 pub file_url: Option<String>,
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
129pub struct UrlCitationContent {
130 pub url: String,
132
133 pub title: String,
135
136 pub start_index: usize,
138
139 pub end_index: usize,
141}
142
143#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
145pub struct RefusalContent {
146 pub refusal: String,
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn test_content_part_output_text() {
156 let part = ContentPart::output_text("Hello, world!");
157 assert_eq!(part.as_text(), Some("Hello, world!"));
158 }
159
160 #[test]
161 fn test_content_part_serialization() {
162 let part = ContentPart::output_text("Test");
163 let json = serde_json::to_string(&part).unwrap();
164 assert!(json.contains("\"type\":\"output_text\""));
165 assert!(json.contains("\"text\":\"Test\""));
166 }
167}