1use client::ClientMessage;
4use compact_str::CompactString;
5use serde::{Deserialize, Serialize};
6use server::ServerMessage;
7use std::collections::BTreeMap;
8
9pub mod client;
10pub mod server;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct AgentSummary {
19 pub name: CompactString,
21 pub description: CompactString,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct McpServerSummary {
28 pub name: CompactString,
30 pub tools: Vec<CompactString>,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct SendRequest {
41 pub agent: CompactString,
43 pub content: String,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct StreamRequest {
50 pub agent: CompactString,
52 pub content: String,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct ClearSessionRequest {
59 pub agent: CompactString,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct AgentInfoRequest {
66 pub agent: CompactString,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct GetMemoryRequest {
73 pub key: String,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct DownloadRequest {
80 pub model: CompactString,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct McpAddRequest {
87 pub name: CompactString,
89 pub command: String,
91 #[serde(default)]
93 pub args: Vec<String>,
94 #[serde(default)]
96 pub env: BTreeMap<String, String>,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct McpRemoveRequest {
102 pub name: CompactString,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct SendResponse {
113 pub agent: CompactString,
115 pub content: String,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct SessionCleared {
122 pub agent: CompactString,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct AgentList {
129 pub agents: Vec<AgentSummary>,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct AgentDetail {
136 pub name: CompactString,
138 pub description: CompactString,
140 pub tools: Vec<CompactString>,
142 pub skill_tags: Vec<CompactString>,
144 pub system_prompt: String,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct MemoryList {
151 pub entries: Vec<(String, String)>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct MemoryEntry {
158 pub key: String,
160 pub value: Option<String>,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct SkillsReloaded {
167 pub count: usize,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct McpAdded {
174 pub name: CompactString,
176 pub tools: Vec<CompactString>,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct McpRemoved {
183 pub name: CompactString,
185 pub tools: Vec<CompactString>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct McpReloaded {
192 pub servers: Vec<McpServerSummary>,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct McpServerList {
199 pub servers: Vec<McpServerSummary>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
209pub enum StreamEvent {
210 Start {
212 agent: CompactString,
214 },
215 Chunk {
217 content: String,
219 },
220 End {
222 agent: CompactString,
224 },
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
229pub enum DownloadEvent {
230 Start {
232 model: CompactString,
234 },
235 FileStart {
237 filename: String,
239 size: u64,
241 },
242 Progress {
244 bytes: u64,
246 },
247 FileEnd {
249 filename: String,
251 },
252 End {
254 model: CompactString,
256 },
257}
258
259impl From<SendRequest> for ClientMessage {
264 fn from(r: SendRequest) -> Self {
265 Self::Send {
266 agent: r.agent,
267 content: r.content,
268 }
269 }
270}
271
272impl From<StreamRequest> for ClientMessage {
273 fn from(r: StreamRequest) -> Self {
274 Self::Stream {
275 agent: r.agent,
276 content: r.content,
277 }
278 }
279}
280
281impl From<ClearSessionRequest> for ClientMessage {
282 fn from(r: ClearSessionRequest) -> Self {
283 Self::ClearSession { agent: r.agent }
284 }
285}
286
287impl From<AgentInfoRequest> for ClientMessage {
288 fn from(r: AgentInfoRequest) -> Self {
289 Self::AgentInfo { agent: r.agent }
290 }
291}
292
293impl From<GetMemoryRequest> for ClientMessage {
294 fn from(r: GetMemoryRequest) -> Self {
295 Self::GetMemory { key: r.key }
296 }
297}
298
299impl From<DownloadRequest> for ClientMessage {
300 fn from(r: DownloadRequest) -> Self {
301 Self::Download { model: r.model }
302 }
303}
304
305impl From<McpAddRequest> for ClientMessage {
306 fn from(r: McpAddRequest) -> Self {
307 Self::McpAdd {
308 name: r.name,
309 command: r.command,
310 args: r.args,
311 env: r.env,
312 }
313 }
314}
315
316impl From<McpRemoveRequest> for ClientMessage {
317 fn from(r: McpRemoveRequest) -> Self {
318 Self::McpRemove { name: r.name }
319 }
320}
321
322impl From<SendResponse> for ServerMessage {
327 fn from(r: SendResponse) -> Self {
328 Self::Response {
329 agent: r.agent,
330 content: r.content,
331 }
332 }
333}
334
335impl From<SessionCleared> for ServerMessage {
336 fn from(r: SessionCleared) -> Self {
337 Self::SessionCleared { agent: r.agent }
338 }
339}
340
341impl From<AgentList> for ServerMessage {
342 fn from(r: AgentList) -> Self {
343 Self::AgentList { agents: r.agents }
344 }
345}
346
347impl From<AgentDetail> for ServerMessage {
348 fn from(r: AgentDetail) -> Self {
349 Self::AgentDetail {
350 name: r.name,
351 description: r.description,
352 tools: r.tools,
353 skill_tags: r.skill_tags,
354 system_prompt: r.system_prompt,
355 }
356 }
357}
358
359impl From<MemoryList> for ServerMessage {
360 fn from(r: MemoryList) -> Self {
361 Self::MemoryList { entries: r.entries }
362 }
363}
364
365impl From<MemoryEntry> for ServerMessage {
366 fn from(r: MemoryEntry) -> Self {
367 Self::MemoryEntry {
368 key: r.key,
369 value: r.value,
370 }
371 }
372}
373
374impl From<SkillsReloaded> for ServerMessage {
375 fn from(r: SkillsReloaded) -> Self {
376 Self::SkillsReloaded { count: r.count }
377 }
378}
379
380impl From<McpAdded> for ServerMessage {
381 fn from(r: McpAdded) -> Self {
382 Self::McpAdded {
383 name: r.name,
384 tools: r.tools,
385 }
386 }
387}
388
389impl From<McpRemoved> for ServerMessage {
390 fn from(r: McpRemoved) -> Self {
391 Self::McpRemoved {
392 name: r.name,
393 tools: r.tools,
394 }
395 }
396}
397
398impl From<McpReloaded> for ServerMessage {
399 fn from(r: McpReloaded) -> Self {
400 Self::McpReloaded { servers: r.servers }
401 }
402}
403
404impl From<McpServerList> for ServerMessage {
405 fn from(r: McpServerList) -> Self {
406 Self::McpServerList { servers: r.servers }
407 }
408}
409
410impl From<StreamEvent> for ServerMessage {
415 fn from(e: StreamEvent) -> Self {
416 match e {
417 StreamEvent::Start { agent } => Self::StreamStart { agent },
418 StreamEvent::Chunk { content } => Self::StreamChunk { content },
419 StreamEvent::End { agent } => Self::StreamEnd { agent },
420 }
421 }
422}
423
424impl From<DownloadEvent> for ServerMessage {
429 fn from(e: DownloadEvent) -> Self {
430 match e {
431 DownloadEvent::Start { model } => Self::DownloadStart { model },
432 DownloadEvent::FileStart { filename, size } => {
433 Self::DownloadFileStart { filename, size }
434 }
435 DownloadEvent::Progress { bytes } => Self::DownloadProgress { bytes },
436 DownloadEvent::FileEnd { filename } => Self::DownloadFileEnd { filename },
437 DownloadEvent::End { model } => Self::DownloadEnd { model },
438 }
439 }
440}
441
442fn unexpected(msg: &str) -> anyhow::Error {
447 anyhow::anyhow!("unexpected response: {msg}")
448}
449
450fn error_or_unexpected(msg: ServerMessage) -> anyhow::Error {
451 match msg {
452 ServerMessage::Error { code, message } => {
453 anyhow::anyhow!("server error ({code}): {message}")
454 }
455 other => unexpected(&format!("{other:?}")),
456 }
457}
458
459impl TryFrom<ServerMessage> for SendResponse {
460 type Error = anyhow::Error;
461 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
462 match msg {
463 ServerMessage::Response { agent, content } => Ok(Self { agent, content }),
464 other => Err(error_or_unexpected(other)),
465 }
466 }
467}
468
469impl TryFrom<ServerMessage> for SessionCleared {
470 type Error = anyhow::Error;
471 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
472 match msg {
473 ServerMessage::SessionCleared { agent } => Ok(Self { agent }),
474 other => Err(error_or_unexpected(other)),
475 }
476 }
477}
478
479impl TryFrom<ServerMessage> for AgentList {
480 type Error = anyhow::Error;
481 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
482 match msg {
483 ServerMessage::AgentList { agents } => Ok(Self { agents }),
484 other => Err(error_or_unexpected(other)),
485 }
486 }
487}
488
489impl TryFrom<ServerMessage> for AgentDetail {
490 type Error = anyhow::Error;
491 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
492 match msg {
493 ServerMessage::AgentDetail {
494 name,
495 description,
496 tools,
497 skill_tags,
498 system_prompt,
499 } => Ok(Self {
500 name,
501 description,
502 tools,
503 skill_tags,
504 system_prompt,
505 }),
506 other => Err(error_or_unexpected(other)),
507 }
508 }
509}
510
511impl TryFrom<ServerMessage> for MemoryList {
512 type Error = anyhow::Error;
513 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
514 match msg {
515 ServerMessage::MemoryList { entries } => Ok(Self { entries }),
516 other => Err(error_or_unexpected(other)),
517 }
518 }
519}
520
521impl TryFrom<ServerMessage> for MemoryEntry {
522 type Error = anyhow::Error;
523 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
524 match msg {
525 ServerMessage::MemoryEntry { key, value } => Ok(Self { key, value }),
526 other => Err(error_or_unexpected(other)),
527 }
528 }
529}
530
531impl TryFrom<ServerMessage> for SkillsReloaded {
532 type Error = anyhow::Error;
533 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
534 match msg {
535 ServerMessage::SkillsReloaded { count } => Ok(Self { count }),
536 other => Err(error_or_unexpected(other)),
537 }
538 }
539}
540
541impl TryFrom<ServerMessage> for McpAdded {
542 type Error = anyhow::Error;
543 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
544 match msg {
545 ServerMessage::McpAdded { name, tools } => Ok(Self { name, tools }),
546 other => Err(error_or_unexpected(other)),
547 }
548 }
549}
550
551impl TryFrom<ServerMessage> for McpRemoved {
552 type Error = anyhow::Error;
553 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
554 match msg {
555 ServerMessage::McpRemoved { name, tools } => Ok(Self { name, tools }),
556 other => Err(error_or_unexpected(other)),
557 }
558 }
559}
560
561impl TryFrom<ServerMessage> for McpReloaded {
562 type Error = anyhow::Error;
563 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
564 match msg {
565 ServerMessage::McpReloaded { servers } => Ok(Self { servers }),
566 other => Err(error_or_unexpected(other)),
567 }
568 }
569}
570
571impl TryFrom<ServerMessage> for McpServerList {
572 type Error = anyhow::Error;
573 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
574 match msg {
575 ServerMessage::McpServerList { servers } => Ok(Self { servers }),
576 other => Err(error_or_unexpected(other)),
577 }
578 }
579}
580
581impl TryFrom<ServerMessage> for StreamEvent {
586 type Error = anyhow::Error;
587 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
588 match msg {
589 ServerMessage::StreamStart { agent } => Ok(Self::Start { agent }),
590 ServerMessage::StreamChunk { content } => Ok(Self::Chunk { content }),
591 ServerMessage::StreamEnd { agent } => Ok(Self::End { agent }),
592 other => Err(error_or_unexpected(other)),
593 }
594 }
595}
596
597impl TryFrom<ServerMessage> for DownloadEvent {
598 type Error = anyhow::Error;
599 fn try_from(msg: ServerMessage) -> anyhow::Result<Self> {
600 match msg {
601 ServerMessage::DownloadStart { model } => Ok(Self::Start { model }),
602 ServerMessage::DownloadFileStart { filename, size } => {
603 Ok(Self::FileStart { filename, size })
604 }
605 ServerMessage::DownloadProgress { bytes } => Ok(Self::Progress { bytes }),
606 ServerMessage::DownloadFileEnd { filename } => Ok(Self::FileEnd { filename }),
607 ServerMessage::DownloadEnd { model } => Ok(Self::End { model }),
608 other => Err(error_or_unexpected(other)),
609 }
610 }
611}