Skip to main content

openresponses_rust/types/
content.rs

1use super::enums::ImageDetail;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
5#[serde(tag = "type")]
6pub enum MessageContent {
7    #[serde(rename = "input_text")]
8    InputText { text: String },
9    #[serde(rename = "input_image")]
10    InputImage {
11        #[serde(skip_serializing_if = "Option::is_none")]
12        image_url: Option<String>,
13        #[serde(default)]
14        detail: ImageDetail,
15    },
16    #[serde(rename = "input_file")]
17    InputFile {
18        #[serde(skip_serializing_if = "Option::is_none")]
19        filename: Option<String>,
20        #[serde(skip_serializing_if = "Option::is_none")]
21        file_data: Option<String>,
22        #[serde(skip_serializing_if = "Option::is_none")]
23        file_url: Option<String>,
24    },
25    #[serde(rename = "input_video")]
26    InputVideo { video_url: String },
27    #[serde(rename = "output_text")]
28    OutputText {
29        text: String,
30        #[serde(default)]
31        annotations: Vec<Annotation>,
32        #[serde(skip_serializing_if = "Option::is_none")]
33        logprobs: Option<Vec<LogProb>>,
34    },
35    #[serde(rename = "refusal")]
36    Refusal { refusal: String },
37    #[serde(rename = "text")]
38    PlainText { text: String },
39    #[serde(rename = "summary_text")]
40    SummaryText { text: String },
41    #[serde(rename = "reasoning_text")]
42    ReasoningText { text: String },
43}
44
45pub type InputContent = MessageContent;
46pub type OutputContent = MessageContent;
47
48impl MessageContent {
49    pub fn input_text<S: Into<String>>(text: S) -> Self {
50        MessageContent::InputText { text: text.into() }
51    }
52
53    pub fn output_text<S: Into<String>>(text: S) -> Self {
54        MessageContent::OutputText {
55            text: text.into(),
56            annotations: Vec::new(),
57            logprobs: None,
58        }
59    }
60
61    pub fn refusal<S: Into<String>>(text: S) -> Self {
62        MessageContent::Refusal {
63            refusal: text.into(),
64        }
65    }
66
67    // Compatibility helpers
68    pub fn text<S: Into<String>>(text: S) -> Self {
69        Self::input_text(text)
70    }
71
72    pub fn image_url<S: Into<String>>(url: S) -> Self {
73        MessageContent::InputImage {
74            image_url: Some(url.into()),
75            detail: ImageDetail::default(),
76        }
77    }
78
79    pub fn image_url_with_detail<S: Into<String>>(url: S, detail: ImageDetail) -> Self {
80        MessageContent::InputImage {
81            image_url: Some(url.into()),
82            detail,
83        }
84    }
85
86    pub fn file_url<S: Into<String>>(url: S) -> Self {
87        MessageContent::InputFile {
88            filename: None,
89            file_data: None,
90            file_url: Some(url.into()),
91        }
92    }
93
94    pub fn file_data<S: Into<String>>(data: S, filename: Option<String>) -> Self {
95        MessageContent::InputFile {
96            filename,
97            file_data: Some(data.into()),
98            file_url: None,
99        }
100    }
101
102    pub fn video_url<S: Into<String>>(url: S) -> Self {
103        MessageContent::InputVideo {
104            video_url: url.into(),
105        }
106    }
107
108    pub fn summary<S: Into<String>>(text: S) -> Self {
109        MessageContent::SummaryText { text: text.into() }
110    }
111
112    pub fn reasoning<S: Into<String>>(text: S) -> Self {
113        MessageContent::ReasoningText { text: text.into() }
114    }
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
118#[serde(tag = "type")]
119pub enum Annotation {
120    #[serde(rename = "url_citation")]
121    UrlCitation {
122        url: String,
123        title: String,
124        start_index: i32,
125        end_index: i32,
126    },
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
130pub struct LogProb {
131    pub token: String,
132    pub logprob: f64,
133    pub bytes: Vec<u8>,
134    pub top_logprobs: Vec<TopLogProb>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
138pub struct TopLogProb {
139    pub token: String,
140    pub logprob: f64,
141    pub bytes: Vec<u8>,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
145#[serde(untagged)]
146pub enum Content {
147    Part(MessageContent),
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
151#[serde(untagged)]
152pub enum ContentParam {
153    Array(Vec<MessageContent>),
154    Single(String),
155}