webterm_agent/models/
relay.rs1use 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}