Skip to main content

walrus_cli/runner/
gateway.rs

1//! Gateway mode — connect to walrusd via Unix domain socket.
2
3use crate::runner::Runner;
4use anyhow::{Result, bail};
5use client::{ClientConfig, Connection, WalrusClient};
6use compact_str::CompactString;
7use futures_core::Stream;
8use protocol::{AgentSummary, ClientMessage, ServerMessage};
9use std::path::Path;
10
11/// Runs agents via a walrusd Unix domain socket connection.
12pub struct GatewayRunner {
13    connection: Connection,
14}
15
16impl GatewayRunner {
17    /// Connect to walrusd.
18    pub async fn connect(socket_path: &Path) -> Result<Self> {
19        let config = ClientConfig {
20            socket_path: socket_path.to_path_buf(),
21        };
22        let client = WalrusClient::new(config);
23        let connection = client.connect().await?;
24        Ok(Self { connection })
25    }
26
27    /// List all registered agents.
28    pub async fn list_agents(&mut self) -> Result<Vec<AgentSummary>> {
29        match self.connection.send(ClientMessage::ListAgents).await? {
30            ServerMessage::AgentList { agents } => Ok(agents),
31            ServerMessage::Error { code, message } => bail!("error ({code}): {message}"),
32            other => bail!("unexpected response: {other:?}"),
33        }
34    }
35
36    /// Get detailed info for a specific agent.
37    pub async fn agent_info(&mut self, agent: &str) -> Result<ServerMessage> {
38        let msg = ClientMessage::AgentInfo {
39            agent: CompactString::from(agent),
40        };
41        self.connection.send(msg).await
42    }
43
44    /// List all memory entries.
45    pub async fn list_memory(&mut self) -> Result<Vec<(String, String)>> {
46        match self.connection.send(ClientMessage::ListMemory).await? {
47            ServerMessage::MemoryList { entries } => Ok(entries),
48            ServerMessage::Error { code, message } => bail!("error ({code}): {message}"),
49            other => bail!("unexpected response: {other:?}"),
50        }
51    }
52
53    /// Send a download request and return a stream of progress messages.
54    pub fn download_stream(
55        &mut self,
56        msg: ClientMessage,
57    ) -> impl Stream<Item = Result<ServerMessage>> + '_ {
58        self.connection.download_stream(msg)
59    }
60
61    /// Get a specific memory entry by key.
62    pub async fn get_memory(&mut self, key: &str) -> Result<Option<String>> {
63        let msg = ClientMessage::GetMemory {
64            key: key.to_string(),
65        };
66        match self.connection.send(msg).await? {
67            ServerMessage::MemoryEntry { value, .. } => Ok(value),
68            ServerMessage::Error { code, message } => bail!("error ({code}): {message}"),
69            other => bail!("unexpected response: {other:?}"),
70        }
71    }
72}
73
74impl Runner for GatewayRunner {
75    async fn send(&mut self, agent: &str, content: &str) -> Result<String> {
76        let msg = ClientMessage::Send {
77            agent: CompactString::from(agent),
78            content: content.to_string(),
79        };
80        match self.connection.send(msg).await? {
81            ServerMessage::Response { content, .. } => Ok(content),
82            ServerMessage::Error { code, message } => {
83                bail!("gateway error ({code}): {message}")
84            }
85            other => bail!("unexpected response: {other:?}"),
86        }
87    }
88
89    fn stream<'a>(
90        &'a mut self,
91        agent: &'a str,
92        content: &'a str,
93    ) -> impl Stream<Item = Result<String>> + Send + 'a {
94        use futures_util::StreamExt;
95
96        let msg = ClientMessage::Stream {
97            agent: CompactString::from(agent),
98            content: content.to_string(),
99        };
100        self.connection.stream(msg).filter_map(|result| async {
101            match result {
102                Ok(ServerMessage::StreamChunk { content }) => Some(Ok(content)),
103                Ok(ServerMessage::StreamStart { .. }) => None,
104                Ok(ServerMessage::Error { code, message }) => {
105                    Some(Err(anyhow::anyhow!("gateway error ({code}): {message}")))
106                }
107                Ok(_) => None,
108                Err(e) => Some(Err(e)),
109            }
110        })
111    }
112}