ldp_protocol/types/session.rs
1//! LDP session types.
2//!
3//! Sessions are governed multi-round contexts — the key difference from
4//! stateless A2A/MCP invocations. Session management is internal to the
5//! adapter; JamJet's workflow engine sees only request→response.
6
7use crate::types::payload::NegotiatedPayload;
8use crate::types::trust::TrustDomain;
9use chrono::{DateTime, Utc};
10use serde::{Deserialize, Serialize};
11
12/// State of an LDP session.
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub enum SessionState {
16 /// HELLO sent, waiting for response.
17 Initiating,
18 /// Session proposed, awaiting acceptance.
19 Proposed,
20 /// Session active — tasks can be submitted.
21 Active,
22 /// Session suspended (can be resumed).
23 Suspended,
24 /// Session terminated.
25 Closed,
26 /// Session failed to establish.
27 Failed,
28}
29
30/// An active LDP session.
31///
32/// Sessions are cached by the `SessionManager` and reused across
33/// multiple `invoke()` calls to the same delegate.
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct LdpSession {
36 /// Unique session identifier.
37 pub session_id: String,
38
39 /// Remote delegate endpoint.
40 pub remote_url: String,
41
42 /// Remote delegate ID.
43 pub remote_delegate_id: String,
44
45 /// Current session state.
46 pub state: SessionState,
47
48 /// Negotiated payload mode for this session.
49 pub payload: NegotiatedPayload,
50
51 /// Trust domain of the remote delegate.
52 pub trust_domain: TrustDomain,
53
54 /// When the session was established.
55 pub created_at: DateTime<Utc>,
56
57 /// When the session was last used.
58 pub last_used: DateTime<Utc>,
59
60 /// Session TTL in seconds (after which it expires if unused).
61 pub ttl_secs: u64,
62
63 /// Number of tasks submitted in this session.
64 pub task_count: u64,
65}
66
67impl LdpSession {
68 /// Check if the session is still active and not expired.
69 pub fn is_active(&self) -> bool {
70 if self.state != SessionState::Active {
71 return false;
72 }
73 let elapsed = Utc::now()
74 .signed_duration_since(self.last_used)
75 .num_seconds();
76 elapsed < self.ttl_secs as i64
77 }
78
79 /// Touch the session (update last_used timestamp).
80 pub fn touch(&mut self) {
81 self.last_used = Utc::now();
82 }
83}
84
85/// Configuration for establishing a new LDP session.
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct SessionConfig {
88 /// Preferred payload modes, ordered by preference.
89 pub preferred_payload_modes: Vec<crate::types::payload::PayloadMode>,
90
91 /// Session TTL in seconds.
92 pub ttl_secs: u64,
93
94 /// Trust domain requirement (if set, only delegates in this domain are accepted).
95 pub required_trust_domain: Option<String>,
96}
97
98impl Default for SessionConfig {
99 fn default() -> Self {
100 Self {
101 preferred_payload_modes: vec![
102 crate::types::payload::PayloadMode::SemanticFrame,
103 crate::types::payload::PayloadMode::Text,
104 ],
105 ttl_secs: 3600, // 1 hour default
106 required_trust_domain: None,
107 }
108 }
109}