webterm_agent/models/
relay.rs

1use crate::models::agent_error::AgentError;
2use tracing::{debug, info};
3use url::Url;
4
5pub struct Relay {
6    host: String,
7    use_http: bool,
8}
9
10impl Relay {
11    pub fn new(host: &str) -> Result<Self, AgentError> {
12        info!("Creating relay with host: {}", host);
13
14        let mut host_with_scheme = host.to_string();
15        if !host.contains("://") {
16            host_with_scheme = format!("https://{}", host);
17        }
18
19        debug!("Parsed relay URL: {}", host_with_scheme);
20        let parsed_url = Url::parse(&host_with_scheme)?;
21        let use_http = match parsed_url.scheme() {
22            "http" => true,
23            "https" => false,
24            _ => {
25                return Err(AgentError::RuntimeError(format!(
26                    "Invalid relay URL scheme: {}",
27                    parsed_url.scheme()
28                )))
29            }
30        };
31
32        let host = parsed_url
33            .host_str()
34            .ok_or(AgentError::RuntimeError(format!(
35                "Couldn't extract host from relay URL: {}",
36                host
37            )))?
38            .to_string();
39
40        let host = match parsed_url.port() {
41            Some(port) => format!("{}:{}", host, port),
42            None => host,
43        };
44
45        Ok(Self { host, use_http })
46    }
47
48    pub fn host(&self) -> &str {
49        &self.host
50    }
51
52    pub fn websocket_url(&self, handshake_nonce: Option<String>) -> String {
53        let scheme = if self.use_http { "ws" } else { "wss" };
54        let mut base = format!("{}://{}/talk/v1/agent", scheme, self.host);
55
56        if let Some(nonce) = handshake_nonce {
57            base = format!("{}?handshake_nonce={}", base, nonce)
58        }
59
60        base
61    }
62
63    pub fn handshake_url(&self) -> String {
64        let scheme = if self.use_http { "http" } else { "https" };
65        format!("{}://{}/handshake/v1/agent", scheme, self.host)
66    }
67}