A rust implementation of skywatch-phash
1use miette::Result;
2use std::sync::Arc;
3use jacquard::client::{Agent, MemoryCredentialSession};
4use jacquard::CowStr;
5
6use crate::config::Config;
7
8/// Agent session wrapper using Jacquard
9/// All internal types use 'static lifetime to enable Send + Sync across threads
10#[derive(Clone)]
11pub struct AgentSession {
12 agent: Arc<Agent<MemoryCredentialSession>>,
13 did: Arc<str>,
14}
15
16impl AgentSession {
17 /// Create a new agent session by authenticating with handle and password
18 pub async fn new(config: &Config) -> Result<Self> {
19 tracing::info!("Logging in as {}", config.automod.handle);
20
21 let handle = CowStr::from(config.automod.handle.clone());
22 let password = CowStr::from(config.automod.password.clone());
23 let pds = Some(CowStr::from(config.ozone.pds.clone()));
24
25 let (session, auth) = MemoryCredentialSession::authenticated(handle, password, pds).await?;
26
27 tracing::info!("Successfully logged in as {} ({})", auth.handle, auth.did);
28
29 let did = Arc::from(auth.did.as_str());
30 let agent = Arc::new(Agent::from(session));
31
32 Ok(Self { agent, did })
33 }
34
35 /// Get the authenticated agent
36 pub fn agent(&self) -> &Arc<Agent<MemoryCredentialSession>> {
37 &self.agent
38 }
39
40 /// Get the authenticated DID
41 pub fn did(&self) -> &str {
42 &*self.did
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 // Note: Integration tests require valid credentials
49}