gproxy-protocol 4.1.14

GPROXY v4 connection modelling, operation declarations, vendor wire types and pairwise conversion
Documentation
use super::*;
use crate::{
    transform::generate::stream::responses::{ResponsesStreamCollector, ResponsesStreamLimits},
    wire::openai::responses::{self as r, stream as s},
};

impl sealed::Event for s::StreamEvent {}
impl NativeEvent for s::StreamEvent {
    type Full = r::GenerateContentResponseBody;
    type Collector = ResponsesStreamCollector;
    fn responses_history(value: &Self::Full) -> Option<&r::GenerateContentResponseBody> {
        Some(value)
    }
    const DIALECT: Dialect = Dialect::OpenAi;
    fn collector(_: IdentityFlow, _: TargetIdPolicy, limits: EventLimits) -> Self::Collector {
        ResponsesStreamCollector::new(ResponsesStreamLimits {
            max_bytes: limits.max_bytes,

            max_text_bytes: limits.max_bytes,
            max_json_bytes: limits.max_bytes,
        })
    }
    fn collect(collector: &mut Self::Collector, event: Self) -> Result<(), TransformError> {
        collector.push(event)
    }
    fn collected(
        collector: Self::Collector,
    ) -> Result<Converted<Collected<Self::Full>>, TransformError> {
        let value = collector.finish()?;
        Ok(Converted {
            value: Collected::native(value.value),
            report: value.report,
        })
    }
    fn event_name(&self) -> Option<&'static str> {
        Some(match self {
            Self::Unknown => return None,
            Self::Keepalive => "keepalive",
            Self::Metadata(_) => "response.metadata",
            Self::Created(_) => "response.created",
            Self::Queued(_) => "response.queued",
            Self::InProgress(_) => "response.in_progress",
            Self::Completed(_) => "response.completed",
            Self::Failed(_) => "response.failed",
            Self::Incomplete(_) => "response.incomplete",
            Self::OutputItemAdded(_) => "response.output_item.added",
            Self::OutputItemDone(_) => "response.output_item.done",
            Self::ContentPartAdded(_) => "response.content_part.added",
            Self::ContentPartDone(_) => "response.content_part.done",
            Self::OutputTextDelta(_) => "response.output_text.delta",
            Self::OutputTextDone(_) => "response.output_text.done",
            Self::OutputTextAnnotationAdded(_) => "response.output_text.annotation.added",
            Self::RefusalDelta(_) => "response.refusal.delta",
            Self::RefusalDone(_) => "response.refusal.done",
            Self::ReasoningTextDelta(_) => "response.reasoning_text.delta",
            Self::ReasoningTextDone(_) => "response.reasoning_text.done",
            Self::ReasoningSummaryPartAdded(_) => "response.reasoning_summary_part.added",
            Self::ReasoningSummaryPartDone(_) => "response.reasoning_summary_part.done",
            Self::ReasoningSummaryTextDelta(_) => "response.reasoning_summary_text.delta",
            Self::ReasoningSummaryTextDone(_) => "response.reasoning_summary_text.done",
            Self::FunctionCallArgumentsDelta(_) => "response.function_call_arguments.delta",
            Self::FunctionCallArgumentsDone(_) => "response.function_call_arguments.done",
            Self::CustomToolInputDelta(_) => "response.custom_tool_call_input.delta",
            Self::CustomToolInputDone(_) => "response.custom_tool_call_input.done",
            Self::CodeInterpreterCodeDelta(_) => "response.code_interpreter_call_code.delta",
            Self::CodeInterpreterCodeDone(_) => "response.code_interpreter_call_code.done",
            Self::AudioDelta(_) => "response.audio.delta",
            Self::AudioDone(_) => "response.audio.done",
            Self::AudioTranscriptDelta(_) => "response.audio.transcript.delta",
            Self::AudioTranscriptDone(_) => "response.audio.transcript.done",
            Self::ImagePartial(_) => "response.image_generation_call.partial_image",
            Self::ImageCall(_) => "response.image_generation_call.in_progress",
            Self::ImageGenerating(_) => "response.image_generation_call.generating",
            Self::ImageCompleted(_) => "response.image_generation_call.completed",
            Self::CodeInterpreterInProgress(_) => "response.code_interpreter_call.in_progress",
            Self::CodeInterpreterInterpreting(_) => "response.code_interpreter_call.interpreting",
            Self::CodeInterpreterCompleted(_) => "response.code_interpreter_call.completed",
            Self::FileSearchInProgress(_) => "response.file_search_call.in_progress",
            Self::FileSearchSearching(_) => "response.file_search_call.searching",
            Self::FileSearchCompleted(_) => "response.file_search_call.completed",
            Self::WebSearchInProgress(_) => "response.web_search_call.in_progress",
            Self::WebSearchSearching(_) => "response.web_search_call.searching",
            Self::WebSearchCompleted(_) => "response.web_search_call.completed",
            Self::McpArgumentsDelta(_) => "response.mcp_call_arguments.delta",
            Self::McpArgumentsDone(_) => "response.mcp_call_arguments.done",
            Self::McpInProgress(_) => "response.mcp_call.in_progress",
            Self::McpCompleted(_) => "response.mcp_call.completed",
            Self::McpFailed(_) => "response.mcp_call.failed",
            Self::McpListToolsInProgress(_) => "response.mcp_list_tools.in_progress",
            Self::McpListToolsCompleted(_) => "response.mcp_list_tools.completed",
            Self::McpListToolsFailed(_) => "response.mcp_list_tools.failed",
            Self::Error(_) => "error",
        })
    }
    fn is_terminal(&self) -> bool {
        matches!(
            self,
            Self::Completed(_) | Self::Incomplete(_) | Self::Failed(_) | Self::Error(_)
        )
    }
    fn tool_declarations(
        &self,
        _complete_tool_names: bool,
    ) -> Vec<(String, ToolCallKind, Option<String>)> {
        let items: Vec<&r::ResponseOutputItem> = match self {
            Self::Created(v) => v.response.output.iter().collect(),
            Self::Queued(v) => v.response.output.iter().collect(),
            Self::InProgress(v) => v.response.output.iter().collect(),
            Self::Completed(v) => v.response.output.iter().collect(),
            Self::Incomplete(v) => v.response.output.iter().collect(),
            Self::OutputItemAdded(v) | Self::OutputItemDone(v) => vec![&v.item],
            _ => Vec::new(),
        };
        items
            .into_iter()
            .filter_map(|item| match item {
                r::ResponseOutputItem::FunctionCall(v) => Some((
                    v.call_id.clone(),
                    ToolCallKind::Function,
                    (!v.name.is_empty()).then(|| {
                        v.namespace.as_ref().map_or_else(
                            || v.name.clone(),
                            |ns| crate::transform::generate::client_tools::qualified(ns, &v.name),
                        )
                    }),
                )),
                r::ResponseOutputItem::ShellCall(v) => Some((
                    v.call_id.clone(),
                    ToolCallKind::Function,
                    Some(crate::transform::generate::client_tools::SHELL.into()),
                )),
                r::ResponseOutputItem::ApplyPatchCall(v) => Some((
                    v.call_id.clone(),
                    ToolCallKind::Function,
                    Some(crate::transform::generate::client_tools::PATCH.into()),
                )),
                r::ResponseOutputItem::ToolSearchCall(v)
                    if v.execution == crate::wire::openai::responses::ToolExecution::Client =>
                {
                    v.call_id.clone().map(|id| {
                        (
                            id,
                            ToolCallKind::Function,
                            Some(crate::transform::generate::client_tools::SEARCH.into()),
                        )
                    })
                }
                r::ResponseOutputItem::CustomToolCall(v) => Some((
                    v.call_id.clone(),
                    ToolCallKind::Custom,
                    (!v.name.is_empty()).then(|| v.name.clone()),
                )),
                _ => None,
            })
            .collect()
    }
}