Skip to main content

crabtalk_core/protocol/message/
convert.rs

1//! Conversions between protocol message types.
2
3use crate::config::ApiStandard;
4use crate::protocol::proto::{
5    AgentEventMsg, ClientMessage, ConversationHistory, PluginEvent, ProviderKind, ReplyToAsk,
6    SendMsg, SendResponse, ServerMessage, StreamEvent, StreamMsg, client_message, plugin_event,
7    server_message, stream_event,
8};
9
10// ── ClientMessage constructors ───────────────────────────────────
11
12impl From<SendMsg> for ClientMessage {
13    fn from(msg: SendMsg) -> Self {
14        Self {
15            msg: Some(client_message::Msg::Send(msg)),
16        }
17    }
18}
19
20impl From<StreamMsg> for ClientMessage {
21    fn from(msg: StreamMsg) -> Self {
22        Self {
23            msg: Some(client_message::Msg::Stream(msg)),
24        }
25    }
26}
27
28impl From<ReplyToAsk> for ClientMessage {
29    fn from(msg: ReplyToAsk) -> Self {
30        Self {
31            msg: Some(client_message::Msg::ReplyToAsk(msg)),
32        }
33    }
34}
35
36// ── ServerMessage constructors ───────────────────────────────────
37
38impl From<SendResponse> for ServerMessage {
39    fn from(r: SendResponse) -> Self {
40        Self {
41            msg: Some(server_message::Msg::Response(r)),
42        }
43    }
44}
45
46impl From<StreamEvent> for ServerMessage {
47    fn from(e: StreamEvent) -> Self {
48        Self {
49            msg: Some(server_message::Msg::Stream(e)),
50        }
51    }
52}
53
54impl From<AgentEventMsg> for ServerMessage {
55    fn from(e: AgentEventMsg) -> Self {
56        Self {
57            msg: Some(server_message::Msg::AgentEvent(e)),
58        }
59    }
60}
61
62impl From<PluginEvent> for ServerMessage {
63    fn from(e: PluginEvent) -> Self {
64        Self {
65            msg: Some(server_message::Msg::PluginEvent(e)),
66        }
67    }
68}
69
70impl From<ConversationHistory> for ServerMessage {
71    fn from(h: ConversationHistory) -> Self {
72        Self {
73            msg: Some(server_message::Msg::ConversationHistory(h)),
74        }
75    }
76}
77
78// ── TryFrom<ServerMessage> ───────────────────────────────────────
79
80fn error_or_unexpected(msg: ServerMessage) -> anyhow::Error {
81    match msg.msg {
82        Some(server_message::Msg::Error(e)) => {
83            anyhow::anyhow!("server error ({}): {}", e.code, e.message)
84        }
85        other => anyhow::anyhow!("unexpected response: {other:?}"),
86    }
87}
88
89impl TryFrom<ServerMessage> for SendResponse {
90    type Error = anyhow::Error;
91    fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
92        match msg.msg {
93            Some(server_message::Msg::Response(r)) => Ok(r),
94            _ => Err(error_or_unexpected(msg)),
95        }
96    }
97}
98
99impl TryFrom<ServerMessage> for stream_event::Event {
100    type Error = anyhow::Error;
101    fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
102        match msg.msg {
103            Some(server_message::Msg::Stream(e)) => {
104                e.event.ok_or_else(|| anyhow::anyhow!("empty stream event"))
105            }
106            _ => Err(error_or_unexpected(msg)),
107        }
108    }
109}
110
111impl From<ApiStandard> for ProviderKind {
112    fn from(kind: ApiStandard) -> Self {
113        match kind {
114            ApiStandard::Openai => Self::Openai,
115            ApiStandard::Anthropic => Self::Anthropic,
116            ApiStandard::Google => Self::Google,
117            ApiStandard::Bedrock => Self::Bedrock,
118            ApiStandard::Ollama => Self::Ollama,
119            ApiStandard::Azure => Self::Azure,
120        }
121    }
122}
123
124impl From<ProviderKind> for ApiStandard {
125    fn from(kind: ProviderKind) -> Self {
126        match kind {
127            ProviderKind::Openai | ProviderKind::Unknown => Self::Openai,
128            ProviderKind::Anthropic => Self::Anthropic,
129            ProviderKind::Google => Self::Google,
130            ProviderKind::Bedrock => Self::Bedrock,
131            ProviderKind::Ollama => Self::Ollama,
132            ProviderKind::Azure => Self::Azure,
133        }
134    }
135}
136
137impl TryFrom<ServerMessage> for plugin_event::Event {
138    type Error = anyhow::Error;
139    fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
140        match msg.msg {
141            Some(server_message::Msg::PluginEvent(e)) => {
142                e.event.ok_or_else(|| anyhow::anyhow!("empty plugin event"))
143            }
144            _ => Err(error_or_unexpected(msg)),
145        }
146    }
147}