gproxy_protocol/adapt/generate/stream/
bridge.rs1use super::event::NativeEvent;
4use crate::{
5 transform::{
6 Converted, Report, TransformError,
7 generate::{
8 chat_responses::stream as hr, claude_chat::stream as ch, claude_gemini::stream as cg,
9 claude_responses::stream as cr, gemini_chat::stream as gh,
10 gemini_responses::stream as gr,
11 },
12 identity::IdentityFlow,
13 },
14 wire::{
15 DeclaredFields,
16 claude::{generate_content as c, stream as cs},
17 gemini as g,
18 openai::{
19 chat::{self as h, stream as hs},
20 responses::{self as r, stream as rs},
21 },
22 },
23};
24use serde::Serialize;
25
26pub(crate) mod sealed {
27 pub trait Bridge {}
28}
29
30pub struct BridgeEnd<E> {
31 pub chunks: Vec<E>,
32 pub identities: IdentityFlow,
33 pub report: Report,
34}
35
36pub trait StreamBridge: sealed::Bridge + Sized {
37 type NativeEvent: NativeEvent;
38 type ClientEvent: NativeEvent;
39 type ClientRequest: Serialize + Clone + DeclaredFields;
40 type NativeRequest: Serialize + Clone + DeclaredFields;
41 fn identities(&self) -> &IdentityFlow;
42 fn push(
43 &mut self,
44 event: Self::NativeEvent,
45 ) -> Result<Converted<Vec<Self::ClientEvent>>, TransformError>;
46 fn push_done(&mut self) -> Result<(), TransformError> {
47 Err(TransformError::invalid_result(
48 "generation.stream",
49 "unexpected native DONE",
50 ))
51 }
52 fn finish(self) -> Result<BridgeEnd<Self::ClientEvent>, TransformError>;
53}
54
55macro_rules! bridge {
56 ($ty:ty, $native:ty, $client:ty, $native_request:ty, $client_request:ty $(, done $done:ident)?) => {
57 impl sealed::Bridge for $ty {}
58 impl StreamBridge for $ty {
59 type NativeEvent = $native;
60 type ClientEvent = $client;
61 type NativeRequest = $native_request;
62 type ClientRequest = $client_request;
63 fn identities(&self) -> &IdentityFlow { <$ty>::identities(self) }
64 fn push(&mut self, event: Self::NativeEvent) -> Result<Converted<Vec<Self::ClientEvent>>, TransformError> { <$ty>::push(self, event) }
65 $(fn push_done(&mut self) -> Result<(), TransformError> { <$ty>::$done(self) })?
66 fn finish(self) -> Result<BridgeEnd<Self::ClientEvent>, TransformError> {
67 let end = <$ty>::finish(self)?;
68 Ok(BridgeEnd { chunks: end.chunks, identities: end.identities, report: end.report })
69 }
70 }
71 };
72}
73bridge!(
74 ch::ClaudeToChatStream,
75 cs::StreamEvent,
76 hs::ChatCompletionChunk,
77 c::GenerateContentRequestBody,
78 h::GenerateContentRequestBody
79);
80bridge!(ch::ChatToClaudeStream, hs::ChatCompletionChunk, cs::StreamEvent, h::GenerateContentRequestBody, c::GenerateContentRequestBody, done push_done);
81bridge!(
82 cg::ClaudeToGeminiStream,
83 cs::StreamEvent,
84 g::GenerateContentResponseBody,
85 c::GenerateContentRequestBody,
86 g::GenerateContentRequestBody
87);
88bridge!(
89 cg::GeminiToClaudeStream,
90 g::GenerateContentResponseBody,
91 cs::StreamEvent,
92 g::GenerateContentRequestBody,
93 c::GenerateContentRequestBody
94);
95bridge!(
96 cr::ClaudeToResponsesStream,
97 cs::StreamEvent,
98 rs::StreamEvent,
99 c::GenerateContentRequestBody,
100 r::GenerateContentRequestBody
101);
102bridge!(
103 cr::ResponsesToClaudeStream,
104 rs::StreamEvent,
105 cs::StreamEvent,
106 r::GenerateContentRequestBody,
107 c::GenerateContentRequestBody
108);
109bridge!(hr::ChatToResponsesStream, hs::ChatCompletionChunk, rs::StreamEvent, h::GenerateContentRequestBody, r::GenerateContentRequestBody, done push_done);
110bridge!(
111 hr::ResponsesToChatStream,
112 rs::StreamEvent,
113 hs::ChatCompletionChunk,
114 r::GenerateContentRequestBody,
115 h::GenerateContentRequestBody
116);
117bridge!(gh::ChatToGeminiStream, hs::ChatCompletionChunk, g::GenerateContentResponseBody, h::GenerateContentRequestBody, g::GenerateContentRequestBody, done push_done);
118bridge!(
119 gh::GeminiToChatStream,
120 g::GenerateContentResponseBody,
121 hs::ChatCompletionChunk,
122 g::GenerateContentRequestBody,
123 h::GenerateContentRequestBody
124);
125bridge!(
126 gr::GeminiToResponsesStream,
127 g::GenerateContentResponseBody,
128 rs::StreamEvent,
129 g::GenerateContentRequestBody,
130 r::GenerateContentRequestBody
131);
132bridge!(
133 gr::ResponsesToGeminiStream,
134 rs::StreamEvent,
135 g::GenerateContentResponseBody,
136 r::GenerateContentRequestBody,
137 g::GenerateContentRequestBody
138);