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::Keepalive => "keepalive",
38 Self::Created(_) => "response.created",
39 Self::Queued(_) => "response.queued",
40 Self::InProgress(_) => "response.in_progress",
41 Self::Completed(_) => "response.completed",
42 Self::Failed(_) => "response.failed",
43 Self::Incomplete(_) => "response.incomplete",
44 Self::OutputItemAdded(_) => "response.output_item.added",
45 Self::OutputItemDone(_) => "response.output_item.done",
46 Self::ContentPartAdded(_) => "response.content_part.added",
47 Self::ContentPartDone(_) => "response.content_part.done",
48 Self::OutputTextDelta(_) => "response.output_text.delta",
49 Self::OutputTextDone(_) => "response.output_text.done",
50 Self::OutputTextAnnotationAdded(_) => "response.output_text.annotation.added",
51 Self::RefusalDelta(_) => "response.refusal.delta",
52 Self::RefusalDone(_) => "response.refusal.done",
53 Self::ReasoningTextDelta(_) => "response.reasoning_text.delta",
54 Self::ReasoningTextDone(_) => "response.reasoning_text.done",
55 Self::ReasoningSummaryPartAdded(_) => "response.reasoning_summary_part.added",
56 Self::ReasoningSummaryPartDone(_) => "response.reasoning_summary_part.done",
57 Self::ReasoningSummaryTextDelta(_) => "response.reasoning_summary_text.delta",
58 Self::ReasoningSummaryTextDone(_) => "response.reasoning_summary_text.done",
59 Self::FunctionCallArgumentsDelta(_) => "response.function_call_arguments.delta",
60 Self::FunctionCallArgumentsDone(_) => "response.function_call_arguments.done",
61 Self::CustomToolInputDelta(_) => "response.custom_tool_call_input.delta",
62 Self::CustomToolInputDone(_) => "response.custom_tool_call_input.done",
63 Self::CodeInterpreterCodeDelta(_) => "response.code_interpreter_call_code.delta",
64 Self::CodeInterpreterCodeDone(_) => "response.code_interpreter_call_code.done",
65 Self::AudioDelta(_) => "response.audio.delta",
66 Self::AudioDone(_) => "response.audio.done",
67 Self::AudioTranscriptDelta(_) => "response.audio.transcript.delta",
68 Self::AudioTranscriptDone(_) => "response.audio.transcript.done",
69 Self::ImagePartial(_) => "response.image_generation_call.partial_image",
70 Self::ImageCall(_) => "response.image_generation_call.in_progress",
71 Self::ImageGenerating(_) => "response.image_generation_call.generating",
72 Self::ImageCompleted(_) => "response.image_generation_call.completed",
73 Self::CodeInterpreterInProgress(_) => "response.code_interpreter_call.in_progress",
74 Self::CodeInterpreterInterpreting(_) => "response.code_interpreter_call.interpreting",
75 Self::CodeInterpreterCompleted(_) => "response.code_interpreter_call.completed",
76 Self::FileSearchInProgress(_) => "response.file_search_call.in_progress",
77 Self::FileSearchSearching(_) => "response.file_search_call.searching",
78 Self::FileSearchCompleted(_) => "response.file_search_call.completed",
79 Self::WebSearchInProgress(_) => "response.web_search_call.in_progress",
80 Self::WebSearchSearching(_) => "response.web_search_call.searching",
81 Self::WebSearchCompleted(_) => "response.web_search_call.completed",
82 Self::McpArgumentsDelta(_) => "response.mcp_call_arguments.delta",
83 Self::McpArgumentsDone(_) => "response.mcp_call_arguments.done",
84 Self::McpInProgress(_) => "response.mcp_call.in_progress",
85 Self::McpCompleted(_) => "response.mcp_call.completed",
86 Self::McpFailed(_) => "response.mcp_call.failed",
87 Self::McpListToolsInProgress(_) => "response.mcp_list_tools.in_progress",
88 Self::McpListToolsCompleted(_) => "response.mcp_list_tools.completed",
89 Self::McpListToolsFailed(_) => "response.mcp_list_tools.failed",
90 Self::Error(_) => "error",
91 })
92 }
93 fn is_terminal(&self) -> bool {
94 matches!(
95 self,
96 Self::Completed(_) | Self::Incomplete(_) | Self::Failed(_) | Self::Error(_)
97 )
98 }
99 fn tool_declarations(
100 &self,
101 _complete_tool_names: bool,
102 ) -> Vec<(String, ToolCallKind, Option<String>)> {
103 let items: Vec<&r::ResponseOutputItem> = match self {
104 Self::Created(v) => v.response.output.iter().collect(),
105 Self::Queued(v) => v.response.output.iter().collect(),
106 Self::InProgress(v) => v.response.output.iter().collect(),
107 Self::Completed(v) => v.response.output.iter().collect(),
108 Self::Incomplete(v) => v.response.output.iter().collect(),
109 Self::OutputItemAdded(v) | Self::OutputItemDone(v) => vec![&v.item],
110 _ => Vec::new(),
111 };
112 items
113 .into_iter()
114 .filter_map(|item| match item {
115 r::ResponseOutputItem::FunctionCall(v) => Some((
116 v.call_id.clone(),
117 ToolCallKind::Function,
118 (!v.name.is_empty()).then(|| {
119 v.namespace.as_ref().map_or_else(
120 || v.name.clone(),
121 |ns| crate::transform::generate::client_tools::qualified(ns, &v.name),
122 )
123 }),
124 )),
125 r::ResponseOutputItem::ShellCall(v) => Some((
126 v.call_id.clone(),
127 ToolCallKind::Function,
128 Some(crate::transform::generate::client_tools::SHELL.into()),
129 )),
130 r::ResponseOutputItem::ApplyPatchCall(v) => Some((
131 v.call_id.clone(),
132 ToolCallKind::Function,
133 Some(crate::transform::generate::client_tools::PATCH.into()),
134 )),
135 r::ResponseOutputItem::ToolSearchCall(v)
136 if v.execution == crate::wire::openai::responses::ToolExecution::Client =>
137 {
138 v.call_id.clone().map(|id| {
139 (
140 id,
141 ToolCallKind::Function,
142 Some(crate::transform::generate::client_tools::SEARCH.into()),
143 )
144 })
145 }
146 r::ResponseOutputItem::CustomToolCall(v) => Some((
147 v.call_id.clone(),
148 ToolCallKind::Custom,
149 (!v.name.is_empty()).then(|| v.name.clone()),
150 )),
151 _ => None,
152 })
153 .collect()
154 }
155}