Skip to main content

agentic_connect/types/
connection.rs

1//! Connection types — core data model for all connections.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7use super::auth::AuthMethod;
8use super::protocol::Protocol;
9
10/// Unique identifier for a connection.
11pub type ConnectionId = Uuid;
12
13/// A configured connection to an external system.
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct Connection {
16    pub id: ConnectionId,
17    pub name: String,
18    pub protocol: Protocol,
19    pub host: String,
20    pub port: Option<u16>,
21    pub path: Option<String>,
22    pub auth: Option<AuthMethod>,
23    pub tags: Vec<String>,
24    pub created_at: DateTime<Utc>,
25    pub last_used: Option<DateTime<Utc>>,
26    pub metadata: serde_json::Value,
27}
28
29impl Connection {
30    /// Create a new connection with auto-detected protocol from URL.
31    pub fn from_url(name: &str, url_str: &str) -> Result<Self, String> {
32        let parsed = url::Url::parse(url_str).map_err(|e| e.to_string())?;
33        let protocol = Protocol::from_scheme(parsed.scheme())
34            .ok_or_else(|| format!("Unknown scheme: {}", parsed.scheme()))?;
35        let host = parsed
36            .host_str()
37            .ok_or("No host in URL")?
38            .to_string();
39        let port = parsed.port().or_else(|| protocol.default_port());
40
41        Ok(Self {
42            id: Uuid::new_v4(),
43            name: name.to_string(),
44            protocol,
45            host,
46            port,
47            path: Some(parsed.path().to_string()).filter(|p| p != "/"),
48            auth: None,
49            tags: Vec::new(),
50            created_at: Utc::now(),
51            last_used: None,
52            metadata: serde_json::Value::Null,
53        })
54    }
55
56    /// Full URL representation of this connection.
57    pub fn url(&self) -> String {
58        let scheme = format!("{:?}", self.protocol).to_lowercase();
59        let port_str = self
60            .port
61            .map(|p| format!(":{}", p))
62            .unwrap_or_default();
63        let path_str = self.path.as_deref().unwrap_or("");
64        format!("{}://{}{}{}", scheme, self.host, port_str, path_str)
65    }
66}
67
68/// Result of a connection attempt.
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ConnectionResult {
71    pub connection_id: ConnectionId,
72    pub success: bool,
73    pub latency_ms: u64,
74    pub protocol_version: Option<String>,
75    pub server_info: Option<String>,
76    pub error: Option<String>,
77    pub timestamp: DateTime<Utc>,
78}
79
80/// A session with a remote system (stateful connection).
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct Session {
83    pub id: Uuid,
84    pub connection_id: ConnectionId,
85    pub started_at: DateTime<Utc>,
86    pub last_activity: DateTime<Utc>,
87    pub request_count: u64,
88    pub bytes_sent: u64,
89    pub bytes_received: u64,
90    pub active: bool,
91}
92
93impl Session {
94    pub fn new(connection_id: ConnectionId) -> Self {
95        let now = Utc::now();
96        Self {
97            id: Uuid::new_v4(),
98            connection_id,
99            started_at: now,
100            last_activity: now,
101            request_count: 0,
102            bytes_sent: 0,
103            bytes_received: 0,
104            active: true,
105        }
106    }
107}