gproxy_protocol/adapt/generate/stream/event/
responses.rs1use super::*;
2use crate::{
3 transform::generate::stream::responses::{ResponsesStreamCollector, ResponsesStreamLimits},
4 wire::openai::responses::{self as r, stream as s},
5};
6
7impl sealed::Event for s::StreamEvent {}
8impl NativeEvent for s::StreamEvent {
9 type Full = r::GenerateContentResponseBody;
10 type Collector = ResponsesStreamCollector;
11 fn responses_history(value: &Self::Full) -> Option<&r::GenerateContentResponseBody> {
12 Some(value)
13 }
14 const DIALECT: Dialect = Dialect::OpenAi;
15 fn collector(_: IdentityFlow, _: TargetIdPolicy, limits: EventLimits) -> Self::Collector {
16 ResponsesStreamCollector::new(ResponsesStreamLimits {
17 max_bytes: limits.max_bytes,
18
19 max_text_bytes: limits.max_bytes,
20 max_json_bytes: limits.max_bytes,
21 })
22 }
23 fn collect(collector: &mut Self::Collector, event: Self) -> Result<(), TransformError> {
24 collector.push(event)
25 }
26 fn collected(
27 collector: Self::Collector,
28 ) -> Result<Converted<Collected<Self::Full>>, TransformError> {
29 let value = collector.finish()?;
30 Ok(Converted {
31 value: Collected::native(value.value),
32 report: value.report,
33 })
34 }
35 fn event_name(&self) -> Option<&'static str> {
36 Some(match self {
37 Self::Unknown => return None,
38 Self::Keepalive => "keepalive",
39 Self::Metadata(_) => "response.metadata",
40 Self::Created(_) => "response.created",
41 Self::Queued(_) => "response.queued",
42 Self::InProgress(_) => "response.in_progress",
43 Self::Completed(_) => "response.completed",
44 Self::Failed(_) => "response.failed",
45 Self::Incomplete(_) => "response.incomplete",
46 Self::OutputItemAdded(_) => "response.output_item.added",
47 Self::OutputItemDone(_) => "response.output_item.done",
48 Self::ContentPartAdded(_) => "response.content_part.added",
49 Self::ContentPartDone(_) => "response.content_part.done",
50 Self::OutputTextDelta(_) => "response.output_text.delta",
51 Self::OutputTextDone(_) => "response.output_text.done",
52 Self::OutputTextAnnotationAdded(_) => "response.output_text.annotation.added",
53 Self::RefusalDelta(_) => "response.refusal.delta",
54 Self::RefusalDone(_) => "response.refusal.done",
55 Self::ReasoningTextDelta(_) => "response.reasoning_text.delta",
56 Self::ReasoningTextDone(_) => "response.reasoning_text.done",
57 Self::ReasoningSummaryPartAdded(_) => "response.reasoning_summary_part.added",
58 Self::ReasoningSummaryPartDone(_) => "response.reasoning_summary_part.done",
59 Self::ReasoningSummaryTextDelta(_) => "response.reasoning_summary_text.delta",
60 Self::ReasoningSummaryTextDone(_) => "response.reasoning_summary_text.done",
61 Self::FunctionCallArgumentsDelta(_) => "response.function_call_arguments.delta",
62 Self::FunctionCallArgumentsDone(_) => "response.function_call_arguments.done",
63 Self::CustomToolInputDelta(_) => "response.custom_tool_call_input.delta",
64 Self::CustomToolInputDone(_) => "response.custom_tool_call_input.done",
65 Self::CodeInterpreterCodeDelta(_) => "response.code_interpreter_call_code.delta",
66 Self::CodeInterpreterCodeDone(_) => "response.code_interpreter_call_code.done",
67 Self::AudioDelta(_) => "response.audio.delta",
68 Self::AudioDone(_) => "response.audio.done",
69 Self::AudioTranscriptDelta(_) => "response.audio.transcript.delta",
70 Self::AudioTranscriptDone(_) => "response.audio.transcript.done",
71 Self::ImagePartial(_) => "response.image_generation_call.partial_image",
72 Self::ImageCall(_) => "response.image_generation_call.in_progress",
73 Self::ImageGenerating(_) => "response.image_generation_call.generating",
74 Self::ImageCompleted(_) => "response.image_generation_call.completed",
75 Self::CodeInterpreterInProgress(_) => "response.code_interpreter_call.in_progress",
76 Self::CodeInterpreterInterpreting(_) => "response.code_interpreter_call.interpreting",
77 Self::CodeInterpreterCompleted(_) => "response.code_interpreter_call.completed",
78 Self::FileSearchInProgress(_) => "response.file_search_call.in_progress",
79 Self::FileSearchSearching(_) => "response.file_search_call.searching",
80 Self::FileSearchCompleted(_) => "response.file_search_call.completed",
81 Self::WebSearchInProgress(_) => "response.web_search_call.in_progress",
82 Self::WebSearchSearching(_) => "response.web_search_call.searching",
83 Self::WebSearchCompleted(_) => "response.web_search_call.completed",
84 Self::McpArgumentsDelta(_) => "response.mcp_call_arguments.delta",
85 Self::McpArgumentsDone(_) => "response.mcp_call_arguments.done",
86 Self::McpInProgress(_) => "response.mcp_call.in_progress",
87 Self::McpCompleted(_) => "response.mcp_call.completed",
88 Self::McpFailed(_) => "response.mcp_call.failed",
89 Self::McpListToolsInProgress(_) => "response.mcp_list_tools.in_progress",
90 Self::McpListToolsCompleted(_) => "response.mcp_list_tools.completed",
91 Self::McpListToolsFailed(_) => "response.mcp_list_tools.failed",
92 Self::Error(_) => "error",
93 })
94 }
95 fn is_terminal(&self) -> bool {
96 matches!(
97 self,
98 Self::Completed(_) | Self::Incomplete(_) | Self::Failed(_) | Self::Error(_)
99 )
100 }
101 fn tool_declarations(
102 &self,
103 _complete_tool_names: bool,
104 ) -> Vec<(String, ToolCallKind, Option<String>)> {
105 let items: Vec<&r::ResponseOutputItem> = match self {
106 Self::Created(v) => v.response.output.iter().collect(),
107 Self::Queued(v) => v.response.output.iter().collect(),
108 Self::InProgress(v) => v.response.output.iter().collect(),
109 Self::Completed(v) => v.response.output.iter().collect(),
110 Self::Incomplete(v) => v.response.output.iter().collect(),
111 Self::OutputItemAdded(v) | Self::OutputItemDone(v) => vec![&v.item],
112 _ => Vec::new(),
113 };
114 items
115 .into_iter()
116 .filter_map(|item| match item {
117 r::ResponseOutputItem::FunctionCall(v) => Some((
118 v.call_id.clone(),
119 ToolCallKind::Function,
120 (!v.name.is_empty()).then(|| {
121 v.namespace.as_ref().map_or_else(
122 || v.name.clone(),
123 |ns| crate::transform::generate::client_tools::qualified(ns, &v.name),
124 )
125 }),
126 )),
127 r::ResponseOutputItem::ShellCall(v) => Some((
128 v.call_id.clone(),
129 ToolCallKind::Function,
130 Some(crate::transform::generate::client_tools::SHELL.into()),
131 )),
132 r::ResponseOutputItem::ApplyPatchCall(v) => Some((
133 v.call_id.clone(),
134 ToolCallKind::Function,
135 Some(crate::transform::generate::client_tools::PATCH.into()),
136 )),
137 r::ResponseOutputItem::ToolSearchCall(v)
138 if v.execution == crate::wire::openai::responses::ToolExecution::Client =>
139 {
140 v.call_id.clone().map(|id| {
141 (
142 id,
143 ToolCallKind::Function,
144 Some(crate::transform::generate::client_tools::SEARCH.into()),
145 )
146 })
147 }
148 r::ResponseOutputItem::CustomToolCall(v) => Some((
149 v.call_id.clone(),
150 ToolCallKind::Custom,
151 (!v.name.is_empty()).then(|| v.name.clone()),
152 )),
153 _ => None,
154 })
155 .collect()
156 }
157}