Skip to main content

va_ai_api_bridge/translator/
mod.rs

1mod anthropic;
2pub mod anthropic_messages;
3mod common;
4pub mod gemini_generate_content;
5mod openai;
6pub mod openai_chat;
7pub mod openai_responses;
8
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11
12use crate::{DecodeState, EncodeState, Result, UniversalEvent, UniversalRequest, WireProtocol};
13
14pub use anthropic_messages::AnthropicMessagesTranslator;
15pub use gemini_generate_content::{
16    GeminiGenerateContentTranslator, GEMINI_SKIP_THOUGHT_SIGNATURE_VALIDATOR,
17};
18pub use openai_chat::OpenAiChatTranslator;
19pub use openai_responses::OpenAiResponsesTranslator;
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct WireEvent {
24    #[serde(default, skip_serializing_if = "Option::is_none")]
25    pub event: Option<String>,
26    pub data: Value,
27}
28
29pub trait WireTranslator {
30    fn protocol(&self) -> WireProtocol;
31
32    fn decode_request(&self, raw: Value) -> Result<UniversalRequest>;
33
34    fn encode_request(&self, request: &UniversalRequest) -> Result<Value>;
35
36    fn decode_response(&self, raw: Value) -> Result<Vec<UniversalEvent>>;
37
38    fn decode_stream_chunk(
39        &self,
40        raw: Value,
41        state: &mut DecodeState,
42    ) -> Result<Vec<UniversalEvent>>;
43
44    fn encode_events(
45        &self,
46        events: &[UniversalEvent],
47        state: &mut EncodeState,
48    ) -> Result<Vec<WireEvent>>;
49}
50
51pub fn translator_for_protocol(protocol: WireProtocol) -> Box<dyn WireTranslator> {
52    match protocol {
53        WireProtocol::OpenAiResponses => Box::new(OpenAiResponsesTranslator),
54        WireProtocol::OpenAiChat => Box::new(OpenAiChatTranslator),
55        WireProtocol::AnthropicMessages => Box::new(AnthropicMessagesTranslator),
56        WireProtocol::GeminiGenerateContent => Box::new(GeminiGenerateContentTranslator),
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use crate::{translator::translator_for_protocol, WireProtocol};
63
64    #[test]
65    fn creates_translator_for_each_wire_protocol() {
66        for protocol in [
67            WireProtocol::OpenAiResponses,
68            WireProtocol::OpenAiChat,
69            WireProtocol::AnthropicMessages,
70            WireProtocol::GeminiGenerateContent,
71        ] {
72            assert_eq!(translator_for_protocol(protocol).protocol(), protocol);
73        }
74    }
75}