shift_preflight/payload/
mod.rs1pub mod anthropic;
2pub mod openai;
3
4use serde_json::Value;
5
6#[derive(Debug, Clone)]
8pub struct ExtractedImage {
9 pub message_index: usize,
11 pub content_index: usize,
13 pub data: Vec<u8>,
15 pub original_ref: ImageRef,
17 pub global_index: usize,
19}
20
21#[derive(Debug, Clone)]
23pub enum ImageRef {
24 DataUri { mime_type: String, base64: String },
26 Base64 { media_type: String, base64: String },
28 Url(String),
30}
31
32pub fn detect_provider(payload: &Value) -> Option<&'static str> {
34 if let Some(messages) = payload.get("messages").and_then(|m| m.as_array()) {
37 for msg in messages {
38 if let Some(content) = msg.get("content").and_then(|c| c.as_array()) {
39 for part in content {
40 if let Some(t) = part.get("type").and_then(|t| t.as_str()) {
41 if t == "image_url" {
42 return Some("openai");
43 }
44 if t == "image" {
45 return Some("anthropic");
46 }
47 }
48 }
49 }
50 }
51 }
52 None
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use serde_json::json;
59
60 #[test]
61 fn test_detect_openai() {
62 let payload = json!({
63 "model": "gpt-4o",
64 "messages": [{
65 "role": "user",
66 "content": [{
67 "type": "image_url",
68 "image_url": {"url": "data:image/png;base64,abc"}
69 }]
70 }]
71 });
72 assert_eq!(detect_provider(&payload), Some("openai"));
73 }
74
75 #[test]
76 fn test_detect_anthropic() {
77 let payload = json!({
78 "model": "claude-sonnet-4-20250514",
79 "messages": [{
80 "role": "user",
81 "content": [{
82 "type": "image",
83 "source": {"type": "base64", "media_type": "image/png", "data": "abc"}
84 }]
85 }]
86 });
87 assert_eq!(detect_provider(&payload), Some("anthropic"));
88 }
89
90 #[test]
91 fn test_detect_text_only() {
92 let payload = json!({
93 "model": "gpt-4o",
94 "messages": [{
95 "role": "user",
96 "content": "Hello world"
97 }]
98 });
99 assert_eq!(detect_provider(&payload), None);
100 }
101}