Skip to main content

Crate gproxy_protocol

Crate gproxy_protocol 

Source
Expand description

§gproxy-protocol

Wire format types and cross-protocol transforms for Claude, OpenAI, and Gemini LLM APIs.

This crate provides two layers:

  1. Protocol types — Serde-compatible request, response, and stream payload structs for each API.
  2. Transforms — Cross-protocol converters that translate requests and responses between any pair of protocols.

§Protocol Modules

ModuleAPIKey Types
claudeAnthropic Messages APICreateMessageRequest, BetaMessage, ClaudeStreamEvent
openaiOpenAI Chat Completions & Responses APIChatCompletionRequest, ResponseBody, ChatCompletionChunk, ResponseStreamEvent
geminiGoogle Gemini GenerateContent APIGeminiGenerateContentRequest, GeminiGenerateContentResponse

Each module follows the same internal structure:

  • types.rs — shared types and enums
  • {operation}/request.rs — request structs
  • {operation}/response.rs — response structs
  • {operation}/stream.rs — stream event payload types (no SSE/NDJSON framing)

§Deserializing a Request

use gproxy_protocol::openai::create_chat_completions::request::RequestBody;

let json = r#"{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}"#;
let body: RequestBody = serde_json::from_str(json).unwrap();
assert_eq!(body.model, "gpt-4");

§Cross-Protocol Transforms

The transform module converts between protocols using Rust’s TryFrom trait. Transforms are organized as transform::{source_protocol}::{operation}::{target_protocol}.

§Non-streaming request conversion

use gproxy_protocol::claude::create_message::request::ClaudeCreateMessageRequest;
use gproxy_protocol::openai::create_chat_completions::request::OpenAiChatCompletionsRequest;

// Claude request → OpenAI ChatCompletions request
fn convert(claude_req: ClaudeCreateMessageRequest) -> Result<OpenAiChatCompletionsRequest, gproxy_protocol::transform::TransformError> {
    OpenAiChatCompletionsRequest::try_from(claude_req)
}

§Streaming response conversion (buffer reuse pattern)

Stream converters process chunks one at a time. The caller provides a reusable Vec buffer to avoid per-chunk heap allocation:

use gproxy_protocol::openai::create_chat_completions::stream::ChatCompletionChunk;
use gproxy_protocol::claude::create_message::stream::ClaudeStreamEvent;
use gproxy_protocol::transform::claude::stream_generate_content::openai_chat_completions::response::OpenAiChatCompletionsToClaudeStream;

let mut converter = OpenAiChatCompletionsToClaudeStream::default();
let mut buf: Vec<ClaudeStreamEvent> = Vec::new();

// For each incoming chunk from upstream:
// converter.on_chunk(chunk, &mut buf);
// buf now contains 0..N output events — forward them, then clear:
// for event in buf.drain(..) { send_downstream(event); }

// When the upstream stream ends:
// converter.finish(&mut buf);
// forward remaining events in buf

§SSE-to-NDJSON Rewriter

The stream module provides an incremental SSE-to-NDJSON byte converter, useful when the downstream expects NDJSON but the internal pipeline uses SSE framing:

use gproxy_protocol::stream::SseToNdjsonRewriter;

let mut rewriter = SseToNdjsonRewriter::default();
let out = rewriter.push_chunk(b"data: {\"text\":\"hi\"}\n\n");
assert_eq!(out, b"{\"text\":\"hi\"}\n");

Re-exports§

pub use kinds::OperationFamily;
pub use kinds::ProtocolKind;

Modules§

claude
Anthropic Claude Messages API wire types.
gemini
Google Gemini API wire types.
kinds
openai
OpenAI API wire types.
stream
transform
Cross-protocol transforms for LLM API requests and responses.