omnyssh_core/event.rs
1//! Domain events and their payload types.
2//!
3//! Background tasks (metrics poller, SFTP, PTY sessions, discovery, the
4//! update checker) report back to the frontend by sending [`CoreEvent`]
5//! values over an `mpsc` channel. Frontends wrap these into their own event
6//! type alongside input events.
7
8use std::time::Instant;
9
10use crate::config::snippets::Snippet;
11use crate::ssh::client::{ConnectionStatus, Host};
12use crate::ssh::key_setup::KeySetupStep;
13use crate::ssh::sftp::FileEntry;
14
15/// Placeholder type aliases for future stages.
16/// `HostId` is the host's `name` field — stable, human-readable key.
17pub type HostId = String;
18pub type SessionId = u64;
19pub type TransferId = u64;
20
21/// A single process entry for the "top processes" panel.
22#[derive(Debug, Clone)]
23pub struct ProcessInfo {
24 /// Process / command name.
25 pub name: String,
26 /// CPU usage percentage.
27 pub cpu_percent: f64,
28 /// Memory usage percentage.
29 pub mem_percent: f64,
30}
31
32/// Live metrics collected from a remote server.
33#[derive(Debug, Clone)]
34pub struct Metrics {
35 pub cpu_percent: Option<f64>,
36 pub ram_percent: Option<f64>,
37 pub disk_percent: Option<f64>,
38 pub uptime: Option<String>,
39 pub load_avg: Option<String>,
40 /// OS information (e.g., "Ubuntu 22.04 LTS", "Debian GNU/Linux 11").
41 pub os_info: Option<String>,
42 /// Top processes by CPU usage (at most 3).
43 pub top_processes: Option<Vec<ProcessInfo>>,
44 /// When these metrics were last successfully collected.
45 pub last_updated: Instant,
46}
47
48impl Default for Metrics {
49 fn default() -> Self {
50 Self {
51 cpu_percent: None,
52 ram_percent: None,
53 disk_percent: None,
54 uptime: None,
55 load_avg: None,
56 os_info: None,
57 top_processes: None,
58 last_updated: Instant::now(),
59 }
60 }
61}
62
63/// Domain events produced by the SSH engine, config loaders, and the update
64/// checker. Background tasks send these over a dedicated channel; the
65/// frontend wraps them into its own event stream.
66#[derive(Debug)]
67pub enum CoreEvent {
68 /// SSH metrics received from a background task.
69 MetricsUpdate(HostId, Metrics),
70 /// Connection status changed for a host (reported by metrics poller).
71 HostStatusChanged(HostId, ConnectionStatus),
72 /// File transfer progress: (transfer_id, bytes_done, bytes_total).
73 FileTransferProgress(TransferId, u64, u64),
74 /// An error message surfaced to the user.
75 Error(String),
76 /// Host list loaded from disk / SSH config in a background task.
77 HostsLoaded(Vec<Host>),
78 /// Snippet list loaded from disk in a background task.
79 SnippetsLoaded(Vec<Snippet>),
80 /// Result of executing a snippet or quick-execute command on one host.
81 /// `output` is `Ok(stdout)` or `Err(error_message)`.
82 SnippetResult {
83 host_name: String,
84 snippet_name: String,
85 output: Result<String, String>,
86 },
87
88 // -----------------------------------------------------------------------
89 // File Manager events
90 // -----------------------------------------------------------------------
91 /// Remote directory listing completed.
92 FileDirListed {
93 path: String,
94 entries: Vec<FileEntry>,
95 },
96 /// Local directory listing completed.
97 LocalDirListed {
98 path: String,
99 entries: Vec<FileEntry>,
100 },
101 /// SFTP session successfully established.
102 SftpConnected { host_name: String },
103 /// SFTP manager ready with established connection (contains SftpManager handle).
104 SftpManagerReady {
105 host_name: String,
106 manager: Box<crate::ssh::sftp::SftpManager>,
107 },
108 /// SFTP session closed or failed.
109 SftpDisconnected { reason: String },
110 /// Preview bytes available for a file.
111 FilePreviewReady { path: String, content: String },
112 /// A mutating SFTP operation (delete, mkdir, rename, upload, download) finished.
113 SftpOpDone { result: Result<(), String> },
114
115 // -----------------------------------------------------------------------
116 // PTY multi-session terminal events
117 // -----------------------------------------------------------------------
118 /// A PTY session produced output. The bytes are already parsed into the
119 /// session's `Arc<Mutex<vt100::Parser>>`; this event is a lightweight
120 /// render-nudge so the main loop can update `has_activity` state without
121 /// copying bulk output data through the channel.
122 PtyOutput(SessionId),
123 /// The PTY child process exited (reader thread reached EOF or I/O error).
124 PtyExited(SessionId),
125
126 // -----------------------------------------------------------------------
127 // Smart Server Context — Discovery events
128 // -----------------------------------------------------------------------
129 /// Quick scan completed for a host, services detected.
130 DiscoveryQuickScanDone(HostId, Vec<DetectedService>),
131 /// Discovery failed for a host with an error message.
132 DiscoveryFailed(HostId, String),
133
134 // -----------------------------------------------------------------------
135 // Auto SSH Key Setup events
136 // -----------------------------------------------------------------------
137 /// Progress update from key setup (host_id, current step, total steps).
138 KeySetupProgress(HostId, KeySetupStep),
139 /// Key setup completed successfully (host_id, private_key_path).
140 KeySetupComplete(HostId, std::path::PathBuf),
141 /// Key setup failed with an error (host_id, error_message).
142 KeySetupFailed(HostId, String),
143 /// Emergency rollback was triggered (host_id, rollback_result).
144 KeySetupRollback(HostId, String),
145
146 // -----------------------------------------------------------------------
147 // Update checker events
148 // -----------------------------------------------------------------------
149 /// A newer release was found on GitHub at startup.
150 UpdateAvailable(crate::update::UpdateInfo),
151 /// A self-update finished — `Ok` on success, `Err` with a message on failure.
152 UpdateInstalled(Result<(), String>),
153}
154
155// ---------------------------------------------------------------------------
156// Smart Server Context — Data structures
157// ---------------------------------------------------------------------------
158
159/// Describes a service detected on a remote server.
160#[derive(Debug, Clone)]
161pub struct DetectedService {
162 pub kind: ServiceKind,
163 pub metrics: Vec<ServiceMetric>,
164}
165
166/// Type of service detected on the server.
167/// Only 5 core services are supported: Docker, Nginx, PostgreSQL, Redis, Node.js.
168#[derive(Debug, Clone, PartialEq, Eq, Hash)]
169pub enum ServiceKind {
170 Docker,
171 Nginx,
172 PostgreSQL,
173 Redis,
174 NodeJS,
175}
176
177/// A metric collected from a specific service.
178#[derive(Debug, Clone)]
179pub struct ServiceMetric {
180 pub name: String, // e.g., "containers_running"
181 pub value: MetricValue, // Typed value
182}
183
184/// Typed metric value.
185#[derive(Debug, Clone)]
186pub enum MetricValue {
187 Integer(i64),
188}