Skip to main content

brainwires_network/
traits.rs

1//! Trait abstractions for decoupling bridge crate from CLI-specific types
2//!
3//! These traits allow the bridge crate to be used as a standalone framework
4//! library, with CLI-specific implementations injected at runtime.
5
6use anyhow::Result;
7use async_trait::async_trait;
8use std::path::PathBuf;
9use zeroize::Zeroizing;
10
11use crate::ipc::protocol::AgentMetadata;
12
13// ============================================================================
14// 1. Path Resolution (replaces PlatformPaths static methods)
15// ============================================================================
16
17/// Provides platform-specific directory paths for IPC sessions and data storage.
18///
19/// CLI implements this wrapping `PlatformPaths` static methods.
20pub trait SessionDir: Send + Sync {
21    /// Directory where agent session files (.sock, .token, .meta.json) are stored
22    fn sessions_dir(&self) -> Result<PathBuf>;
23
24    /// Path to the authentication session file (session.json)
25    fn session_file(&self) -> Result<PathBuf>;
26
27    /// Base data directory for application data
28    fn data_dir(&self) -> Result<PathBuf>;
29}
30
31// ============================================================================
32// 2. Secure Key Storage (replaces keyring module coupling)
33// ============================================================================
34
35/// Trait for secure credential storage (system keyring, encrypted file, etc).
36///
37/// CLI implements this with the `keyring` crate (GNOME Keyring, macOS Keychain,
38/// Windows Credential Manager).
39pub trait KeyStore: Send + Sync {
40    /// Store a key for a given user ID
41    fn store_key(&self, user_id: &str, key: &str) -> Result<()>;
42
43    /// Retrieve a key for a given user ID (returns Zeroizing for secure memory clearing)
44    fn get_key(&self, user_id: &str) -> Result<Option<Zeroizing<String>>>;
45
46    /// Delete the key for a given user ID
47    fn delete_key(&self, user_id: &str) -> Result<()>;
48
49    /// Check if the key store backend is available on this system
50    fn is_available(&self) -> bool;
51}
52
53// ============================================================================
54// 3. Backend URL Configuration (replaces config::constants)
55// ============================================================================
56
57/// Provides authentication endpoint configuration.
58///
59/// CLI implements this reading from `config::constants`.
60pub trait AuthEndpoints: Send + Sync {
61    /// Full URL for the CLI authentication endpoint (e.g., `https://brainwires.studio/api/cli/auth`)
62    fn auth_endpoint(&self) -> String;
63
64    /// Regex pattern for validating API key format
65    fn api_key_pattern(&self) -> &str;
66
67    /// Base backend URL (e.g., `https://brainwires.studio`)
68    fn backend_url(&self) -> &str;
69}
70
71// ============================================================================
72// 4. Agent Process Creation (replaces spawn_agent_process_with_options)
73// ============================================================================
74
75/// Trait for spawning new agent processes.
76///
77/// CLI implements this wrapping `spawn_agent_process_with_options`.
78#[async_trait]
79pub trait AgentSpawner: Send + Sync {
80    /// Spawn a new agent process and return the socket path.
81    ///
82    /// # Arguments
83    /// * `session_id` - Unique session identifier for the new agent
84    /// * `model` - Optional AI model to use
85    /// * `working_directory` - Optional working directory for the agent
86    async fn spawn_agent(
87        &self,
88        session_id: &str,
89        model: Option<String>,
90        working_directory: Option<PathBuf>,
91    ) -> Result<PathBuf>;
92}
93
94// ============================================================================
95// 5. Agent Discovery (replaces IPC socket statics bound to PlatformPaths)
96// ============================================================================
97
98/// Trait for discovering and managing running agents.
99///
100/// CLI implements this by delegating to the bridge's discovery module
101/// with `PlatformPaths::sessions_dir()` injected.
102#[async_trait]
103pub trait AgentDiscovery: Send + Sync {
104    /// List all agents with their metadata
105    fn list_agents_with_metadata(&self) -> Result<Vec<AgentMetadata>>;
106
107    /// Clean up stale agent sockets (dead processes)
108    async fn cleanup_stale(&self) -> Result<()>;
109
110    /// Check if an agent is alive and accepting connections
111    async fn is_agent_alive(&self, session_id: &str) -> bool;
112}
113
114// ============================================================================
115// 6. Remote Bridge Configuration (replaces ConfigManager + SessionManager coupling)
116// ============================================================================
117
118/// Configuration for the remote bridge (extracted from CLI's RemoteSettings + BridgeConfig)
119#[derive(Debug, Clone)]
120pub struct RemoteBridgeConfig {
121    /// Backend base URL
122    pub backend_url: String,
123    /// API key for authentication
124    pub api_key: String,
125    /// Heartbeat interval in seconds
126    pub heartbeat_interval_secs: u32,
127    /// Reconnect delay in seconds
128    pub reconnect_delay_secs: u32,
129    /// Maximum reconnect attempts (0 = unlimited)
130    pub max_reconnect_attempts: u32,
131}
132
133/// Provides remote bridge configuration and API key access.
134///
135/// CLI implements this using `ConfigManager` + `SessionManager`.
136pub trait BridgeConfigProvider: Send + Sync {
137    /// Get the remote bridge configuration (returns None if not enabled)
138    fn get_remote_config(&self) -> Result<Option<RemoteBridgeConfig>>;
139
140    /// Get the API key (from keyring or session, Zeroizing for secure memory)
141    fn get_api_key(&self) -> Result<Option<Zeroizing<String>>>;
142}