Skip to main content

systemprompt_wire/
protocol.rs

1//! Wire-protocol family for an upstream AI provider.
2//!
3//! [`WireProtocol`] names the *request/response shape* a provider speaks, not
4//! the vendor. It is the single key that both the gateway's outbound adapters
5//! and the agent-flow provider clients resolve a wire codec from: `minimax`
6//! speaks [`WireProtocol::Anthropic`]; `moonshot` and `qwen` speak
7//! [`WireProtocol::OpenAiChat`]. Decoupling the protocol from the provider name
8//! is what lets a new vendor reuse an existing codec by declaring its protocol.
9//!
10//! Copyright (c) systemprompt.io — Business Source License 1.1.
11//! See <https://systemprompt.io> for licensing details.
12
13use serde::{Deserialize, Serialize};
14
15use crate::schema::ProviderCapabilities;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, schemars::JsonSchema)]
18pub enum WireProtocol {
19    #[serde(rename = "anthropic")]
20    Anthropic,
21    #[serde(rename = "openai-chat", alias = "openai_chat", alias = "openai")]
22    OpenAiChat,
23    #[serde(rename = "openai-responses", alias = "openai_responses")]
24    OpenAiResponses,
25    #[serde(rename = "gemini")]
26    Gemini,
27}
28
29impl WireProtocol {
30    #[must_use]
31    pub const fn as_tag(self) -> &'static str {
32        match self {
33            Self::Anthropic => "anthropic",
34            Self::OpenAiChat => "openai-chat",
35            Self::OpenAiResponses => "openai-responses",
36            Self::Gemini => "gemini",
37        }
38    }
39
40    #[must_use]
41    pub fn from_tag(tag: &str) -> Option<Self> {
42        match tag {
43            "anthropic" => Some(Self::Anthropic),
44            "openai-chat" | "openai_chat" | "openai" => Some(Self::OpenAiChat),
45            "openai-responses" | "openai_responses" => Some(Self::OpenAiResponses),
46            "gemini" => Some(Self::Gemini),
47            _ => None,
48        }
49    }
50
51    #[must_use]
52    pub const fn schema_capabilities(self) -> ProviderCapabilities {
53        match self {
54            Self::Anthropic => ProviderCapabilities::anthropic(),
55            Self::OpenAiChat | Self::OpenAiResponses => ProviderCapabilities::openai(),
56            Self::Gemini => ProviderCapabilities::gemini(),
57        }
58    }
59}
60
61impl std::fmt::Display for WireProtocol {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        f.write_str(self.as_tag())
64    }
65}