mirror of
https://github.com/whit3rabbit/anyllm-proxy.git
synced 2026-09-21 16:00:49 +00:00
Rust workspace with two crates: - translator: pure, IO-free mapping between Anthropic Messages API and OpenAI Chat Completions - proxy: axum HTTP server with auth, streaming SSE, retry/backoff, concurrency limits 169 tests passing (unit, golden fixture, integration). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.2 KiB
2.2 KiB
Streaming Protocol Differences
Anthropic SSE Event Sequence
event: message_start
data: {"type":"message_start","message":{...initial message with empty content...}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" world"}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":15}}
event: message_stop
data: {"type":"message_stop"}
OpenAI Chat Completions Streaming
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" world"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":5,"total_tokens":15}}
data: [DONE]
Translation State Machine
The StreamingTranslator converts OpenAI chunks to Anthropic events:
- First chunk -> emit
message_startwith empty content - Text delta -> emit
content_block_start(if not open) +content_block_deltawithtext_delta - Tool call start (has
id) -> close any open text block, emitcontent_block_startwithtool_use - Tool call args -> emit
content_block_deltawithinput_json_delta - finish_reason -> close open blocks, emit
message_deltawith mapped stop_reason - [DONE] -> emit
message_stop
Backpressure
- Bounded mpsc channel (capacity 32) between upstream reader and SSE emitter
- Client disconnect detected via
tx.send().is_err() - Upstream connection dropped when receiver is dropped