claudius/types/
document_block.rs

1use serde::{Deserialize, Serialize};
2
3use crate::types::{
4    Base64PdfSource, CacheControlEphemeral, CitationsConfig, ContentBlockSourceParam,
5    PlainTextSource, UrlPdfSource,
6};
7
8/// The source type for a document block, which can be one of several types.
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
10#[serde(tag = "type")]
11pub enum DocumentSource {
12    /// A Base64 encoded PDF source.
13    #[serde(rename = "base64")]
14    Base64Pdf(Base64PdfSource),
15
16    /// A plain text source.
17    #[serde(rename = "text")]
18    PlainText(PlainTextSource),
19
20    /// A content block source.
21    #[serde(rename = "content")]
22    ContentBlock(ContentBlockSourceParam),
23
24    /// A URL PDF source.
25    #[serde(rename = "url")]
26    UrlPdf(UrlPdfSource),
27}
28
29/// Parameters for a document block.
30#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
31pub struct DocumentBlock {
32    /// The source of the document.
33    pub source: DocumentSource,
34
35    /// Create a cache control breakpoint at this content block.
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub cache_control: Option<CacheControlEphemeral>,
38
39    /// Configuration for citations in this document.
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub citations: Option<CitationsConfig>,
42
43    /// Optional context for the document.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub context: Option<String>,
46
47    /// Optional title for the document.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub title: Option<String>,
50}
51
52impl DocumentBlock {
53    /// Create a new `DocumentBlock` with the given source.
54    pub fn new(source: DocumentSource) -> Self {
55        Self {
56            source,
57            cache_control: None,
58            citations: None,
59            context: None,
60            title: None,
61        }
62    }
63
64    /// Create a new `DocumentBlock` with a Base64 PDF source.
65    pub fn new_with_base64_pdf(source: Base64PdfSource) -> Self {
66        Self::new(DocumentSource::Base64Pdf(source))
67    }
68
69    /// Create a new `DocumentBlock` with a plain text source.
70    pub fn new_with_plain_text(source: PlainTextSource) -> Self {
71        Self::new(DocumentSource::PlainText(source))
72    }
73
74    /// Create a new `DocumentBlock` with a content block source.
75    pub fn new_with_content_block(source: ContentBlockSourceParam) -> Self {
76        Self::new(DocumentSource::ContentBlock(source))
77    }
78
79    /// Create a new `DocumentBlock` with a URL PDF source.
80    pub fn new_with_url_pdf(source: UrlPdfSource) -> Self {
81        Self::new(DocumentSource::UrlPdf(source))
82    }
83
84    /// Add a cache control to this document block.
85    pub fn with_cache_control(mut self, cache_control: CacheControlEphemeral) -> Self {
86        self.cache_control = Some(cache_control);
87        self
88    }
89
90    /// Add citations configuration to this document block.
91    pub fn with_citations(mut self, citations: CitationsConfig) -> Self {
92        self.citations = Some(citations);
93        self
94    }
95
96    /// Add context to this document block.
97    pub fn with_context(mut self, context: String) -> Self {
98        self.context = Some(context);
99        self
100    }
101
102    /// Add a title to this document block.
103    pub fn with_title(mut self, title: String) -> Self {
104        self.title = Some(title);
105        self
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112    use serde_json::{json, to_value};
113
114    #[test]
115    fn document_block_with_base64_pdf() {
116        let base64_source =
117            Base64PdfSource::new("data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKN".to_string());
118
119        let document_block = DocumentBlock::new_with_base64_pdf(base64_source);
120        let json = to_value(&document_block).unwrap();
121
122        assert_eq!(
123            json,
124            json!({
125                "source": {
126                    "type": "base64",
127                    "data": "data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKN",
128                    "media_type": "application/pdf"
129                }
130            })
131        );
132    }
133
134    #[test]
135    fn document_block_with_plain_text() {
136        let text_source = PlainTextSource::new("Sample text content".to_string());
137
138        let document_block = DocumentBlock::new_with_plain_text(text_source);
139        let json = to_value(&document_block).unwrap();
140
141        assert_eq!(
142            json,
143            json!({
144                "source": {
145                    "type": "text",
146                    "data": "Sample text content",
147                    "media_type": "text/plain"
148                }
149            })
150        );
151    }
152
153    #[test]
154    fn document_block_with_content_block() {
155        let content_source = ContentBlockSourceParam::from_string_ref("Sample content");
156
157        let document_block = DocumentBlock::new_with_content_block(content_source);
158        let json = to_value(&document_block).unwrap();
159
160        assert_eq!(
161            json,
162            json!({
163                "source": {
164                    "type": "content",
165                    "content": "Sample content"
166                }
167            })
168        );
169    }
170
171    #[test]
172    fn document_block_with_url_pdf() {
173        let url_source = UrlPdfSource::new("https://example.com/document.pdf".to_string());
174
175        let document_block = DocumentBlock::new_with_url_pdf(url_source);
176        let json = to_value(&document_block).unwrap();
177
178        assert_eq!(
179            json,
180            json!({
181                "source": {
182                    "type": "url",
183                    "url": "https://example.com/document.pdf"
184                }
185            })
186        );
187    }
188
189    #[test]
190    fn document_block_with_all_fields() {
191        let url_source = UrlPdfSource::new("https://example.com/document.pdf".to_string());
192        let cache_control = CacheControlEphemeral::new();
193        let citations = CitationsConfig::enabled();
194
195        let document_block = DocumentBlock::new_with_url_pdf(url_source)
196            .with_cache_control(cache_control)
197            .with_citations(citations)
198            .with_context("Document context".to_string())
199            .with_title("Document Title".to_string());
200
201        let json = to_value(&document_block).unwrap();
202
203        assert_eq!(
204            json,
205            json!({
206                "source": {
207                    "type": "url",
208                    "url": "https://example.com/document.pdf"
209                },
210                "cache_control": {
211                    "type": "ephemeral"
212                },
213                "citations": {
214                    "enabled": true
215                },
216                "context": "Document context",
217                "title": "Document Title"
218            })
219        );
220    }
221}