use crate::hub;
use crate::{AgentRegistration, Message};
pub struct RemoteRelay {
base_url: String,
}
impl RemoteRelay {
pub fn new(server_url: &str) -> Self {
let base_url = server_url.trim_end_matches('/').to_string();
Self { base_url }
}
pub fn health(&self) -> Result<String, String> {
let resp = ureq::get(&format!("{}/health", self.base_url))
.call()
.map_err(|e| format!("Connection failed: {}", e))?;
resp.into_string().map_err(|e| format!("Read error: {}", e))
}
pub fn register(
&self,
agent_id: &str,
session_id: &str,
pid: u32,
) -> Result<AgentRegistration, String> {
let resp = ureq::post(&format!("{}/agents/register", self.base_url))
.send_json(serde_json::json!({
"session_id": session_id,
"agent_id": agent_id,
"pid": pid,
}))
.map_err(|e| format!("Request failed: {}", e))?;
let body: AgentRegistration = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
Ok(body)
}
pub fn unregister(&self, session_id: &str) -> Result<(), String> {
ureq::post(&format!("{}/agents/unregister", self.base_url))
.send_json(serde_json::json!({"session_id": session_id}))
.map_err(|e| format!("Request failed: {}", e))?;
Ok(())
}
pub fn agents(&self) -> Result<Vec<AgentRegistration>, String> {
let resp = ureq::get(&format!("{}/agents", self.base_url))
.call()
.map_err(|e| format!("Request failed: {}", e))?;
let body: Vec<AgentRegistration> = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
Ok(body)
}
pub fn send(
&self,
from_session: &str,
from_agent: &str,
to_session: Option<&str>,
content: &str,
) -> Result<Message, String> {
self.send_scoped(from_session, from_agent, to_session, content, None, None)
}
pub fn send_scoped(
&self,
from_session: &str,
from_agent: &str,
to_session: Option<&str>,
content: &str,
team_id: Option<&str>,
channel: Option<&str>,
) -> Result<Message, String> {
let resp = ureq::post(&format!("{}/messages/send", self.base_url))
.send_json(serde_json::json!({
"from_session": from_session,
"from_agent": from_agent,
"to_session": to_session,
"content": content,
"team_id": team_id,
"channel": channel,
}))
.map_err(|e| format!("Request failed: {}", e))?;
let body: Message = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
Ok(body)
}
pub fn inbox(&self, session_id: &str, limit: usize) -> Result<Vec<Message>, String> {
self.inbox_scoped(session_id, limit, None, None)
}
pub fn inbox_scoped(
&self,
session_id: &str,
limit: usize,
team: Option<&str>,
channel: Option<&str>,
) -> Result<Vec<Message>, String> {
let mut url = format!(
"{}/messages/inbox?session={}&limit={}",
self.base_url, session_id, limit
);
if let Some(t) = team {
url.push_str(&format!("&team={}", t));
}
if let Some(c) = channel {
url.push_str(&format!("&channel={}", c));
}
let resp = ureq::get(&url)
.call()
.map_err(|e| format!("Request failed: {}", e))?;
let body: Vec<Message> = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
Ok(body)
}
pub fn unread_count(&self, session_id: &str) -> Result<u64, String> {
let resp = ureq::get(&format!(
"{}/messages/unread?session={}",
self.base_url, session_id
))
.call()
.map_err(|e| format!("Request failed: {}", e))?;
let body: serde_json::Value = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
Ok(body["count"].as_u64().unwrap_or(0))
}
pub fn signup(&self, email: &str, name: &str) -> Result<(String, String), String> {
let resp = ureq::post(&format!("{}/auth/signup", self.base_url))
.send_json(serde_json::json!({ "email": email, "name": name }))
.map_err(|e| format!("Request failed: {}", e))?;
let body: serde_json::Value = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
let user_id = body["user"]["id"]
.as_str()
.ok_or("Missing user.id in response")?
.to_string();
let api_key = body["api_key"]
.as_str()
.ok_or("Missing api_key in response")?
.to_string();
Ok((user_id, api_key))
}
pub fn login(&self, email: &str) -> Result<String, String> {
let resp = ureq::post(&format!("{}/auth/login", self.base_url))
.send_json(serde_json::json!({ "email": email }))
.map_err(|e| format!("Request failed: {}", e))?;
let body: serde_json::Value = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
body["api_key"]
.as_str()
.map(|s| s.to_string())
.ok_or("Missing api_key in response".to_string())
}
pub fn create_team(&self, api_key: &str, name: &str) -> Result<hub::Team, String> {
let resp = ureq::post(&format!("{}/teams", self.base_url))
.set("Authorization", &format!("Bearer {}", api_key))
.send_json(serde_json::json!({ "name": name }))
.map_err(|e| format!("Request failed: {}", e))?;
resp.into_json().map_err(|e| format!("Parse error: {}", e))
}
pub fn list_teams(&self, api_key: &str) -> Result<Vec<hub::Team>, String> {
let resp = ureq::get(&format!("{}/teams", self.base_url))
.set("Authorization", &format!("Bearer {}", api_key))
.call()
.map_err(|e| format!("Request failed: {}", e))?;
resp.into_json().map_err(|e| format!("Parse error: {}", e))
}
pub fn invite(
&self,
api_key: &str,
team_id: &str,
email: Option<&str>,
) -> Result<String, String> {
let resp = ureq::post(&format!("{}/teams/{}/invite", self.base_url, team_id))
.set("Authorization", &format!("Bearer {}", api_key))
.send_json(serde_json::json!({ "email": email }))
.map_err(|e| format!("Request failed: {}", e))?;
let body: serde_json::Value = resp
.into_json()
.map_err(|e| format!("Parse error: {}", e))?;
body["token"]
.as_str()
.map(|s| s.to_string())
.ok_or("Missing token in response".to_string())
}
pub fn join_team(&self, api_key: &str, token: &str) -> Result<(), String> {
ureq::post(&format!("{}/teams/join", self.base_url))
.set("Authorization", &format!("Bearer {}", api_key))
.send_json(serde_json::json!({ "token": token }))
.map_err(|e| format!("Request failed: {}", e))?;
Ok(())
}
pub fn list_members(
&self,
api_key: &str,
team_id: &str,
) -> Result<Vec<hub::TeamMember>, String> {
let resp = ureq::get(&format!("{}/teams/{}/members", self.base_url, team_id))
.set("Authorization", &format!("Bearer {}", api_key))
.call()
.map_err(|e| format!("Request failed: {}", e))?;
resp.into_json().map_err(|e| format!("Parse error: {}", e))
}
pub fn kick_member(
&self,
api_key: &str,
team_id: &str,
user_id: &str,
) -> Result<(), String> {
ureq::post(&format!("{}/teams/{}/kick", self.base_url, team_id))
.set("Authorization", &format!("Bearer {}", api_key))
.send_json(serde_json::json!({ "user_id": user_id }))
.map_err(|e| format!("Request failed: {}", e))?;
Ok(())
}
pub fn create_channel(
&self,
api_key: &str,
team_id: &str,
name: &str,
) -> Result<hub::Channel, String> {
let resp = ureq::post(&format!(
"{}/teams/{}/channels",
self.base_url, team_id
))
.set("Authorization", &format!("Bearer {}", api_key))
.send_json(serde_json::json!({ "name": name }))
.map_err(|e| format!("Request failed: {}", e))?;
resp.into_json().map_err(|e| format!("Parse error: {}", e))
}
pub fn list_channels(
&self,
api_key: &str,
team_id: &str,
) -> Result<Vec<hub::Channel>, String> {
let resp = ureq::get(&format!(
"{}/teams/{}/channels",
self.base_url, team_id
))
.set("Authorization", &format!("Bearer {}", api_key))
.call()
.map_err(|e| format!("Request failed: {}", e))?;
resp.into_json().map_err(|e| format!("Parse error: {}", e))
}
}