gproxy-protocol 2.9.10

GPROXY protocol types and endpoint metadata
Documentation
use serde::{Deserialize, Serialize};

use super::super::common::*;
use super::{ResponseCreateRequest, ResponseInput, ResponseStreamEvent};

pub type ResponseWebSocketWireModel =
    OpenAiWireModel<ResponseWebSocketRequest, ResponseStreamEvent>;

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
#[allow(clippy::large_enum_variant)]
#[non_exhaustive]
pub enum ResponseWebSocketRequest {
    #[serde(rename = "response.create")]
    ResponseCreate(ResponseCreateWebSocketRequest),
    #[serde(rename = "response.steer")]
    ResponseSteer(ResponseSteerWebSocketRequest),
}

#[derive(
    Debug, Clone, PartialEq, Serialize, Deserialize, Default, gproxy_protocol_macros::WireBuilder,
)]
#[non_exhaustive]
pub struct ResponseCreateWebSocketRequest {
    #[serde(flatten)]
    pub response: ResponseCreateRequest,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub generate: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub client_metadata: Option<Metadata>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
#[non_exhaustive]
pub struct ResponseSteerWebSocketRequest {
    pub previous_response_id: String,
    pub input: ResponseInput,
    #[serde(
        default,
        flatten,
        skip_serializing_if = "std::collections::BTreeMap::is_empty"
    )]
    pub extra: Extra,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
#[non_exhaustive]
pub struct ResponseSteerReference {
    pub id: String,
    pub previous_response_id: String,
    #[serde(
        default,
        flatten,
        skip_serializing_if = "std::collections::BTreeMap::is_empty"
    )]
    pub extra: Extra,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
#[non_exhaustive]
pub struct ResponseSteerFailure {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
    pub previous_response_id: String,
    pub input: ResponseInput,
    #[serde(
        default,
        flatten,
        skip_serializing_if = "std::collections::BTreeMap::is_empty"
    )]
    pub extra: Extra,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
#[non_exhaustive]
pub struct ResponseSteerError {
    pub code: String,
    pub message: String,
    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
    pub type_: Option<String>,
    #[serde(
        default,
        flatten,
        skip_serializing_if = "std::collections::BTreeMap::is_empty"
    )]
    pub extra: Extra,
}

#[cfg(test)]
mod tests {
    use serde_json::json;

    use super::*;
    use crate::protocol::openai::{OpenAiModelId, ResponseInput};

    #[test]
    fn response_create_frame_round_trips_websocket_fields() {
        let value = json!({
            "type": "response.create",
            "model": "gpt-x",
            "input": "hello",
            "stream": true,
            "generate": false,
            "client_metadata": {
                "x-codex-installation-id": "installation-1"
            }
        });

        let parsed: ResponseWebSocketRequest = serde_json::from_value(value).unwrap();
        let ResponseWebSocketRequest::ResponseCreate(frame) = parsed else {
            panic!("expected response.create")
        };
        assert_eq!(
            frame.response.model,
            Some(OpenAiModelId::Unknown("gpt-x".to_owned()))
        );
        assert_eq!(
            frame.response.input,
            Some(ResponseInput::Text("hello".to_owned()))
        );
        assert_eq!(frame.response.stream, Some(true));
        assert_eq!(frame.generate, Some(false));
        assert_eq!(
            frame
                .client_metadata
                .as_ref()
                .and_then(|m| m.get("x-codex-installation-id")),
            Some(&"installation-1".to_owned())
        );

        let serialized = serde_json::to_value(ResponseWebSocketRequest::ResponseCreate(frame))
            .expect("serialize websocket response.create");
        assert_eq!(serialized["type"], json!("response.create"));
        assert_eq!(serialized["generate"], json!(false));
    }
}