1use crate::protocol::message::{client::ClientMessage, server::ServerMessage};
4use compact_str::CompactString;
5use serde::{Deserialize, Serialize};
6use std::collections::BTreeMap;
7
8pub mod client;
9pub mod server;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct AgentSummary {
18 pub name: CompactString,
20 pub description: CompactString,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct McpServerSummary {
27 pub name: CompactString,
29 pub tools: Vec<CompactString>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct SendRequest {
40 pub agent: CompactString,
42 pub content: String,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct StreamRequest {
49 pub agent: CompactString,
51 pub content: String,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct ClearSessionRequest {
58 pub agent: CompactString,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct AgentInfoRequest {
65 pub agent: CompactString,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct GetMemoryRequest {
72 pub key: String,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct DownloadRequest {
79 pub model: CompactString,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct McpAddRequest {
86 pub name: CompactString,
88 pub command: String,
90 #[serde(default)]
92 pub args: Vec<String>,
93 #[serde(default)]
95 pub env: BTreeMap<String, String>,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct McpRemoveRequest {
101 pub name: CompactString,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct SendResponse {
112 pub agent: CompactString,
114 pub content: String,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
120pub struct SessionCleared {
121 pub agent: CompactString,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct AgentList {
128 pub agents: Vec<AgentSummary>,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct AgentDetail {
135 pub name: CompactString,
137 pub description: CompactString,
139 pub tools: Vec<CompactString>,
141 pub skill_tags: Vec<CompactString>,
143 pub system_prompt: String,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct MemoryList {
150 pub entries: Vec<(String, String)>,
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct MemoryEntry {
157 pub key: String,
159 pub value: Option<String>,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct SkillsReloaded {
166 pub count: usize,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct McpAdded {
173 pub name: CompactString,
175 pub tools: Vec<CompactString>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct McpRemoved {
182 pub name: CompactString,
184 pub tools: Vec<CompactString>,
186}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct McpReloaded {
191 pub servers: Vec<McpServerSummary>,
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct McpServerList {
198 pub servers: Vec<McpServerSummary>,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
208pub enum StreamEvent {
209 Start {
211 agent: CompactString,
213 },
214 Chunk {
216 content: String,
218 },
219 End {
221 agent: CompactString,
223 },
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
228pub enum DownloadEvent {
229 Start {
231 model: CompactString,
233 },
234 FileStart {
236 filename: String,
238 size: u64,
240 },
241 Progress {
243 bytes: u64,
245 },
246 FileEnd {
248 filename: String,
250 },
251 End {
253 model: CompactString,
255 },
256}
257
258impl From<SendRequest> for ClientMessage {
263 fn from(r: SendRequest) -> Self {
264 Self::Send {
265 agent: r.agent,
266 content: r.content,
267 }
268 }
269}
270
271impl From<StreamRequest> for ClientMessage {
272 fn from(r: StreamRequest) -> Self {
273 Self::Stream {
274 agent: r.agent,
275 content: r.content,
276 }
277 }
278}
279
280impl From<ClearSessionRequest> for ClientMessage {
281 fn from(r: ClearSessionRequest) -> Self {
282 Self::ClearSession { agent: r.agent }
283 }
284}
285
286impl From<AgentInfoRequest> for ClientMessage {
287 fn from(r: AgentInfoRequest) -> Self {
288 Self::AgentInfo { agent: r.agent }
289 }
290}
291
292impl From<GetMemoryRequest> for ClientMessage {
293 fn from(r: GetMemoryRequest) -> Self {
294 Self::GetMemory { key: r.key }
295 }
296}
297
298impl From<DownloadRequest> for ClientMessage {
299 fn from(r: DownloadRequest) -> Self {
300 Self::Download { model: r.model }
301 }
302}
303
304impl From<McpAddRequest> for ClientMessage {
305 fn from(r: McpAddRequest) -> Self {
306 Self::McpAdd {
307 name: r.name,
308 command: r.command,
309 args: r.args,
310 env: r.env,
311 }
312 }
313}
314
315impl From<McpRemoveRequest> for ClientMessage {
316 fn from(r: McpRemoveRequest) -> Self {
317 Self::McpRemove { name: r.name }
318 }
319}
320
321impl From<SendResponse> for ServerMessage {
326 fn from(r: SendResponse) -> Self {
327 Self::Response {
328 agent: r.agent,
329 content: r.content,
330 }
331 }
332}
333
334impl From<SessionCleared> for ServerMessage {
335 fn from(r: SessionCleared) -> Self {
336 Self::SessionCleared { agent: r.agent }
337 }
338}
339
340impl From<AgentList> for ServerMessage {
341 fn from(r: AgentList) -> Self {
342 Self::AgentList { agents: r.agents }
343 }
344}
345
346impl From<AgentDetail> for ServerMessage {
347 fn from(r: AgentDetail) -> Self {
348 Self::AgentDetail {
349 name: r.name,
350 description: r.description,
351 tools: r.tools,
352 skill_tags: r.skill_tags,
353 system_prompt: r.system_prompt,
354 }
355 }
356}
357
358impl From<MemoryList> for ServerMessage {
359 fn from(r: MemoryList) -> Self {
360 Self::MemoryList { entries: r.entries }
361 }
362}
363
364impl From<MemoryEntry> for ServerMessage {
365 fn from(r: MemoryEntry) -> Self {
366 Self::MemoryEntry {
367 key: r.key,
368 value: r.value,
369 }
370 }
371}
372
373impl From<SkillsReloaded> for ServerMessage {
374 fn from(r: SkillsReloaded) -> Self {
375 Self::SkillsReloaded { count: r.count }
376 }
377}
378
379impl From<McpAdded> for ServerMessage {
380 fn from(r: McpAdded) -> Self {
381 Self::McpAdded {
382 name: r.name,
383 tools: r.tools,
384 }
385 }
386}
387
388impl From<McpRemoved> for ServerMessage {
389 fn from(r: McpRemoved) -> Self {
390 Self::McpRemoved {
391 name: r.name,
392 tools: r.tools,
393 }
394 }
395}
396
397impl From<McpReloaded> for ServerMessage {
398 fn from(r: McpReloaded) -> Self {
399 Self::McpReloaded { servers: r.servers }
400 }
401}
402
403impl From<McpServerList> for ServerMessage {
404 fn from(r: McpServerList) -> Self {
405 Self::McpServerList { servers: r.servers }
406 }
407}
408
409impl From<StreamEvent> for ServerMessage {
414 fn from(e: StreamEvent) -> Self {
415 match e {
416 StreamEvent::Start { agent } => Self::StreamStart { agent },
417 StreamEvent::Chunk { content } => Self::StreamChunk { content },
418 StreamEvent::End { agent } => Self::StreamEnd { agent },
419 }
420 }
421}
422
423impl From<DownloadEvent> for ServerMessage {
428 fn from(e: DownloadEvent) -> Self {
429 match e {
430 DownloadEvent::Start { model } => Self::DownloadStart { model },
431 DownloadEvent::FileStart { filename, size } => {
432 Self::DownloadFileStart { filename, size }
433 }
434 DownloadEvent::Progress { bytes } => Self::DownloadProgress { bytes },
435 DownloadEvent::FileEnd { filename } => Self::DownloadFileEnd { filename },
436 DownloadEvent::End { model } => Self::DownloadEnd { model },
437 }
438 }
439}
440
441fn unexpected(msg: &str) -> anyhow::Error {
446 anyhow::anyhow!("unexpected response: {msg}")
447}
448
449fn error_or_unexpected(msg: ServerMessage) -> anyhow::Error {
450 match msg {
451 ServerMessage::Error { code, message } => {
452 anyhow::anyhow!("server error ({code}): {message}")
453 }
454 other => unexpected(&format!("{other:?}")),
455 }
456}
457
458impl TryFrom<ServerMessage> for SendResponse {
459 type Error = anyhow::Error;
460 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
461 match msg {
462 ServerMessage::Response { agent, content } => Ok(Self { agent, content }),
463 other => Err(error_or_unexpected(other)),
464 }
465 }
466}
467
468impl TryFrom<ServerMessage> for SessionCleared {
469 type Error = anyhow::Error;
470 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
471 match msg {
472 ServerMessage::SessionCleared { agent } => Ok(Self { agent }),
473 other => Err(error_or_unexpected(other)),
474 }
475 }
476}
477
478impl TryFrom<ServerMessage> for AgentList {
479 type Error = anyhow::Error;
480 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
481 match msg {
482 ServerMessage::AgentList { agents } => Ok(Self { agents }),
483 other => Err(error_or_unexpected(other)),
484 }
485 }
486}
487
488impl TryFrom<ServerMessage> for AgentDetail {
489 type Error = anyhow::Error;
490 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
491 match msg {
492 ServerMessage::AgentDetail {
493 name,
494 description,
495 tools,
496 skill_tags,
497 system_prompt,
498 } => Ok(Self {
499 name,
500 description,
501 tools,
502 skill_tags,
503 system_prompt,
504 }),
505 other => Err(error_or_unexpected(other)),
506 }
507 }
508}
509
510impl TryFrom<ServerMessage> for MemoryList {
511 type Error = anyhow::Error;
512 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
513 match msg {
514 ServerMessage::MemoryList { entries } => Ok(Self { entries }),
515 other => Err(error_or_unexpected(other)),
516 }
517 }
518}
519
520impl TryFrom<ServerMessage> for MemoryEntry {
521 type Error = anyhow::Error;
522 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
523 match msg {
524 ServerMessage::MemoryEntry { key, value } => Ok(Self { key, value }),
525 other => Err(error_or_unexpected(other)),
526 }
527 }
528}
529
530impl TryFrom<ServerMessage> for SkillsReloaded {
531 type Error = anyhow::Error;
532 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
533 match msg {
534 ServerMessage::SkillsReloaded { count } => Ok(Self { count }),
535 other => Err(error_or_unexpected(other)),
536 }
537 }
538}
539
540impl TryFrom<ServerMessage> for McpAdded {
541 type Error = anyhow::Error;
542 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
543 match msg {
544 ServerMessage::McpAdded { name, tools } => Ok(Self { name, tools }),
545 other => Err(error_or_unexpected(other)),
546 }
547 }
548}
549
550impl TryFrom<ServerMessage> for McpRemoved {
551 type Error = anyhow::Error;
552 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
553 match msg {
554 ServerMessage::McpRemoved { name, tools } => Ok(Self { name, tools }),
555 other => Err(error_or_unexpected(other)),
556 }
557 }
558}
559
560impl TryFrom<ServerMessage> for McpReloaded {
561 type Error = anyhow::Error;
562 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
563 match msg {
564 ServerMessage::McpReloaded { servers } => Ok(Self { servers }),
565 other => Err(error_or_unexpected(other)),
566 }
567 }
568}
569
570impl TryFrom<ServerMessage> for McpServerList {
571 type Error = anyhow::Error;
572 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
573 match msg {
574 ServerMessage::McpServerList { servers } => Ok(Self { servers }),
575 other => Err(error_or_unexpected(other)),
576 }
577 }
578}
579
580impl TryFrom<ServerMessage> for StreamEvent {
585 type Error = anyhow::Error;
586 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
587 match msg {
588 ServerMessage::StreamStart { agent } => Ok(Self::Start { agent }),
589 ServerMessage::StreamChunk { content } => Ok(Self::Chunk { content }),
590 ServerMessage::StreamEnd { agent } => Ok(Self::End { agent }),
591 other => Err(error_or_unexpected(other)),
592 }
593 }
594}
595
596impl TryFrom<ServerMessage> for DownloadEvent {
597 type Error = anyhow::Error;
598 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
599 match msg {
600 ServerMessage::DownloadStart { model } => Ok(Self::Start { model }),
601 ServerMessage::DownloadFileStart { filename, size } => {
602 Ok(Self::FileStart { filename, size })
603 }
604 ServerMessage::DownloadProgress { bytes } => Ok(Self::Progress { bytes }),
605 ServerMessage::DownloadFileEnd { filename } => Ok(Self::FileEnd { filename }),
606 ServerMessage::DownloadEnd { model } => Ok(Self::End { model }),
607 other => Err(error_or_unexpected(other)),
608 }
609 }
610}