Skip to main content

gproxy_protocol/openai/generate_content/responses/items/
mod.rs

1mod actions;
2mod agent;
3mod content;
4mod message;
5mod typed;
6
7pub use actions::*;
8pub use agent::*;
9pub use content::*;
10pub use message::*;
11pub use typed::*;
12
13use serde::{Deserialize, Serialize, de};
14use serde_json::Value;
15
16use crate::openai::common::{ResponseItemType, ResponseItemTypeKnown, Rest};
17
18#[derive(Debug, Clone, PartialEq, Serialize)]
19#[serde(untagged)]
20#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
21pub enum ResponseItem {
22    Message(ResponseMessageItem),
23    Typed(Box<TypedResponseItem>),
24    Unknown(Value),
25}
26
27impl<'de> Deserialize<'de> for ResponseItem {
28    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
29        let value = Value::deserialize(deserializer)?;
30        let Some(type_name) = value.get("type").and_then(Value::as_str) else {
31            if let Ok(message) = serde_json::from_value::<ResponseMessageItem>(value.clone()) {
32                return Ok(Self::Message(message));
33            }
34            if let Some(item) = item_reference_without_type(&value) {
35                return Ok(Self::Typed(Box::new(item)));
36            }
37            return Ok(Self::Unknown(value));
38        };
39        let item_type = serde_json::from_value::<ResponseItemType>(Value::String(type_name.into()))
40            .map_err(de::Error::custom)?;
41        match item_type {
42            ResponseItemType::Known(ResponseItemTypeKnown::Message) => {
43                serde_json::from_value(value)
44                    .map(Self::Message)
45                    .map_err(de::Error::custom)
46            }
47            ResponseItemType::Known(_) => match serde_json::from_value(value.clone()) {
48                Ok(item) => Ok(Self::Typed(Box::new(item))),
49                Err(_) => Ok(Self::Unknown(value)),
50            },
51            ResponseItemType::Unknown(_) => Ok(Self::Unknown(value)),
52        }
53    }
54}
55
56fn item_reference_without_type(value: &Value) -> Option<TypedResponseItem> {
57    let object = value.as_object()?;
58    let id = object.get("id")?.as_str()?.to_owned();
59    let rest: Rest = object
60        .iter()
61        .filter(|(key, _)| key.as_str() != "id")
62        .map(|(key, value)| (key.clone(), value.clone()))
63        .collect();
64    Some(TypedResponseItem::ItemReference { id, rest })
65}
66
67pub type ResponseOutputItem = ResponseItem;