Skip to main content

systemprompt_api/services/gateway/protocol/outbound/
mod.rs

1pub mod anthropic;
2pub mod openai_chat;
3pub mod openai_responses;
4
5use std::sync::Arc;
6
7use anyhow::Result;
8use async_trait::async_trait;
9use futures_util::stream::BoxStream;
10use systemprompt_models::profile::GatewayRoute;
11
12use super::canonical::CanonicalRequest;
13use super::canonical_response::{CanonicalEvent, CanonicalResponse};
14
15#[derive(Debug)]
16pub struct OutboundCtx<'a> {
17    pub route: &'a GatewayRoute,
18    pub endpoint: &'a str,
19    pub api_key: &'a str,
20    pub request: &'a CanonicalRequest,
21    pub upstream_model: &'a str,
22}
23
24#[expect(
25    missing_debug_implementations,
26    reason = "variants hold streaming bodies that intentionally do not implement Debug"
27)]
28pub enum OutboundOutcome {
29    Buffered(CanonicalResponse),
30    Streaming(BoxStream<'static, Result<CanonicalEvent, String>>),
31}
32
33// Why: #[async_trait] is required — the upstream registry stores adapters as
34// `Arc<dyn OutboundAdapter>`, so the trait must stay dyn-compatible.
35#[async_trait]
36pub trait OutboundAdapter: Send + Sync {
37    fn provider_tag(&self) -> &'static str;
38    async fn send(&self, ctx: OutboundCtx<'_>) -> Result<OutboundOutcome>;
39}
40
41#[derive(Debug, Clone, Copy)]
42pub struct OutboundAdapterRegistration {
43    pub tag: &'static str,
44    pub factory: fn() -> Arc<dyn OutboundAdapter>,
45}
46
47inventory::collect!(OutboundAdapterRegistration);