Skip to main content

systemprompt_api/services/gateway/protocol/inbound/anthropic_messages/
mod.rs

1use bytes::Bytes;
2use http::StatusCode;
3use serde_json::Value;
4
5use super::super::canonical::CanonicalRequest;
6use super::super::canonical_response::{CanonicalEvent, CanonicalResponse};
7use super::{InboundAdapter, InboundParseError};
8
9mod parse;
10mod render;
11
12pub use render::content_to_anthropic_block;
13
14#[derive(Debug, Clone, Copy, Default)]
15pub struct AnthropicMessagesInbound;
16
17impl InboundAdapter for AnthropicMessagesInbound {
18    fn wire_name(&self) -> &'static str {
19        "anthropic.messages"
20    }
21
22    fn parse_request(&self, raw: &Bytes) -> Result<CanonicalRequest, InboundParseError> {
23        let value: Value = serde_json::from_slice(raw)
24            .map_err(|e| InboundParseError::InvalidJson(e.to_string()))?;
25        parse::parse(&value)
26    }
27
28    fn render_response(&self, response: &CanonicalResponse) -> Bytes {
29        let value = render::render_response_value(response);
30        Bytes::from(serde_json::to_vec(&value).unwrap_or_else(|_| b"{}".to_vec()))
31    }
32
33    fn render_event(&self, event: &CanonicalEvent, model: &str) -> Option<Bytes> {
34        render::render_event_frame(event, model)
35    }
36
37    fn render_error(&self, _status: StatusCode, message: &str) -> Bytes {
38        let escaped = message.replace('\\', "\\\\").replace('"', "\\\"");
39        let body = format!(
40            "{{\"type\":\"error\",\"error\":{{\"type\":\"api_error\",\"message\":\"{escaped}\"}}}}"
41        );
42        Bytes::from(body)
43    }
44}