mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
- Introduced detailed architecture overview outlining system components and entry points. - Documented state management using Redux Toolkit and Redux-Persist, including store configuration and slice structures. - Described services layer architecture, detailing API client, socket service, and MTProto service functionalities. - Explained the Model Context Protocol (MCP) system, including tool categories and implementation examples. - Outlined routing structure and page components, emphasizing protected and public routes. - Organized reusable components by feature, detailing their structure and usage. - Provided insights into provider management for service lifecycle and shared state. This documentation enhances understanding of the application's structure and improves onboarding for new developers, ensuring clarity in the system's design and functionality.
6.9 KiB
6.9 KiB
Services Documentation
This document describes the background services in the Rust backend.
SessionService
Manages user sessions with secure OS keychain storage.
Location
src-tauri/src/services/session_service.rs
Purpose
- Store authentication tokens securely in OS keychain
- Cache session in memory for fast access
- Persist sessions across app restarts
API
pub struct SessionService {
// ...
}
impl SessionService {
/// Create a new SessionService (loads from keychain)
pub fn new() -> Self;
/// Store a new session
pub fn store_session(&self, token: &str, user: &User) -> Result<(), String>;
/// Get the current session token
pub fn get_token(&self) -> Option<String>;
/// Get the current session
pub fn get_session(&self) -> Option<Session>;
/// Get the current user
pub fn get_user(&self) -> Option<User>;
/// Check if there's an active session
pub fn is_authenticated(&self) -> bool;
/// Clear the current session (logout)
pub fn clear_session(&self) -> Result<(), String>;
}
Keychain Storage
| Platform | Storage Backend |
|---|---|
| macOS | Keychain |
| Windows | Credential Manager |
| Linux | Secret Service (libsecret) |
Stored Data
{
"token": "jwt-session-token",
"user_id": "user-uuid",
"user": {
"id": "user-uuid",
"firstName": "John",
"lastName": "Doe"
},
"created_at": 1706540000,
"expires_at": null
}
Usage
use crate::commands::auth::SESSION_SERVICE;
// Store session
SESSION_SERVICE.store_session("token", &user)?;
// Get token
if let Some(token) = SESSION_SERVICE.get_token() {
// Use token
}
// Check auth
if SESSION_SERVICE.is_authenticated() {
// User is logged in
}
// Logout
SESSION_SERVICE.clear_session()?;
SocketService
Manages Socket.io connection state and coordinates with the frontend.
Location
src-tauri/src/services/socket_service.rs
Purpose
- Track socket connection state
- Store connection parameters for reconnection
- Emit events to frontend for connection control
- Enable background socket persistence
Architecture
The actual Socket.io client runs in the frontend (JavaScript). The Rust service:
- Stores connection parameters (URL, token)
- Tracks state reported by frontend
- Emits events to request connect/disconnect
- Enables socket to persist when window is hidden
API
pub struct SocketService {
// ...
}
impl SocketService {
/// Create a new SocketService
pub fn new() -> Self;
/// Set app handle for event emission
pub fn set_app_handle(&self, handle: AppHandle);
/// Get current connection status
pub fn get_status(&self) -> ConnectionStatus;
/// Get current socket state
pub fn get_state(&self) -> SocketState;
/// Check if connected
pub fn is_connected(&self) -> bool;
/// Request frontend to connect
pub fn request_connect(&self, backend_url: &str, token: &str) -> Result<(), String>;
/// Request frontend to disconnect
pub fn request_disconnect(&self) -> Result<(), String>;
/// Update status (called by frontend via command)
pub fn update_status(&self, status: ConnectionStatus, socket_id: Option<String>);
/// Report connection (called by frontend)
pub fn report_connected(&self, socket_id: Option<String>);
/// Report disconnection (called by frontend)
pub fn report_disconnected(&self);
/// Report error (called by frontend)
pub fn report_error(&self, error: &str);
/// Get stored connection params for reconnection
pub fn get_connection_params(&self) -> Option<(String, String)>;
/// Clear stored credentials
pub fn clear_credentials(&self);
}
Events Emitted
| Event | Payload | When |
|---|---|---|
socket:should_connect |
{ backendUrl, token } |
request_connect called |
socket:should_disconnect |
() |
request_disconnect called |
socket:state_changed |
SocketState |
State changes |
socket:error |
string |
Error reported |
Connection States
pub enum ConnectionStatus {
Disconnected,
Connecting,
Connected,
Reconnecting,
Error,
}
Usage
use crate::services::socket_service::SOCKET_SERVICE;
// Initialize with app handle
SOCKET_SERVICE.set_app_handle(app.handle());
// Request connection (emits event to frontend)
SOCKET_SERVICE.request_connect("https://api.example.com", "token")?;
// Check status
if SOCKET_SERVICE.is_connected() {
// Socket is connected
}
// Frontend reports status via commands
// invoke('report_socket_connected', { socketId: 'abc' })
Background Persistence
When the window is hidden:
- The Tauri app continues running (tray icon)
- The WebView is not destroyed, just hidden
- Socket.io connection in JavaScript stays active
- Frontend continues receiving messages
- User can show window to see updates
NotificationService
Shows native desktop notifications.
Location
src-tauri/src/services/notification_service.rs
Purpose
- Show native notifications
- Check notification permission
- Request notification permission
API
pub struct NotificationService;
impl NotificationService {
/// Show a simple notification
pub fn show(app: &AppHandle, title: &str, body: &str) -> Result<(), String>;
/// Show a notification with an icon
pub fn show_with_icon(
app: &AppHandle,
title: &str,
body: &str,
icon: &str,
) -> Result<(), String>;
/// Show a notification for a new message
pub fn show_message_notification(
app: &AppHandle,
sender: &str,
message: &str,
) -> Result<(), String>;
/// Check if notifications are permitted
pub fn is_permission_granted(app: &AppHandle) -> Result<bool, String>;
/// Request notification permission
pub fn request_permission(app: &AppHandle) -> Result<bool, String>;
}
Usage
use crate::services::notification_service::NotificationService;
// Show notification
NotificationService::show(&app, "New Message", "You have a new message")?;
// Show message notification
NotificationService::show_message_notification(&app, "John", "Hey, how are you?")?;
// Check permission
if NotificationService::is_permission_granted(&app)? {
// Can show notifications
}
Service Initialization
Services are initialized as singletons in their respective modules:
// In auth.rs
pub static SESSION_SERVICE: Lazy<Arc<SessionService>> =
Lazy::new(|| Arc::new(SessionService::new()));
// In socket_service.rs
pub static SOCKET_SERVICE: Lazy<Arc<SocketService>> =
Lazy::new(|| Arc::new(SocketService::new()));
The SocketService's app handle is set during app setup:
// In lib.rs setup()
SOCKET_SERVICE.set_app_handle(app.handle().clone());
Previous: Commands Reference | Back to Index