use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionMode {
Managed,
Detected,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionStatus {
Running,
Succeeded,
Failed,
Cancelled,
Lost,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum OutputStream {
Stdout,
Stderr,
System,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Severity {
Error,
Warning,
Note,
Help,
Info,
Success,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SessionInfo {
pub session_id: String,
pub mode: SessionMode,
pub title: String,
pub command: Vec<String>,
pub cwd: PathBuf,
pub workspace_root: Option<PathBuf>,
pub started_at: OffsetDateTime,
pub status: SessionStatus,
pub external_pid: Option<u32>,
pub classification: Option<DetectedProcessClass>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct LogEntry {
pub sequence: u64,
pub timestamp: OffsetDateTime,
pub stream: OutputStream,
pub text: String,
pub raw: Option<String>,
pub severity: Option<Severity>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DiagnosticRecord {
pub id: String,
pub timestamp: OffsetDateTime,
pub severity: Severity,
pub message: String,
pub rendered: Option<String>,
pub code: Option<String>,
pub file: Option<PathBuf>,
pub line: Option<u32>,
pub column: Option<u32>,
pub target: Option<String>,
pub package_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ArtifactRecord {
pub sequence: u64,
pub timestamp: OffsetDateTime,
pub package_id: Option<String>,
pub target: Option<String>,
pub filenames: Vec<PathBuf>,
pub executable: Option<PathBuf>,
pub fresh: bool,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct SummaryCounts {
pub errors: u32,
pub warnings: u32,
pub notes: u32,
pub help: u32,
pub info: u32,
}
impl SummaryCounts {
pub fn observe(&mut self, severity: Severity) {
match severity {
Severity::Error => self.errors += 1,
Severity::Warning => self.warnings += 1,
Severity::Note => self.notes += 1,
Severity::Help => self.help += 1,
Severity::Info | Severity::Success => self.info += 1,
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum DetectedProcessClass {
CargoBuild,
CargoCheck,
CargoTest,
CargoClippy,
CargoDoc,
RustcCompile,
Rustdoc,
UnknownRustProcess,
}
impl DetectedProcessClass {
pub fn label(self) -> &'static str {
match self {
Self::CargoBuild => "cargo build",
Self::CargoCheck => "cargo check",
Self::CargoTest => "cargo test",
Self::CargoClippy => "cargo clippy",
Self::CargoDoc => "cargo doc",
Self::RustcCompile => "rustc compile",
Self::Rustdoc => "rustdoc",
Self::UnknownRustProcess => "rust process",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DetectedProcess {
pub session_id: String,
pub pid: u32,
pub process_name: String,
pub command: Vec<String>,
pub cwd: Option<PathBuf>,
pub workspace_root: Option<PathBuf>,
pub classification: DetectedProcessClass,
pub started_at: OffsetDateTime,
pub last_seen_at: OffsetDateTime,
pub elapsed_ms: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SessionFinished {
pub session_id: String,
pub finished_at: OffsetDateTime,
pub status: SessionStatus,
pub exit_code: Option<i32>,
pub duration_ms: i64,
pub summary: SummaryCounts,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionEvent {
SessionStarted(SessionInfo),
OutputLine {
session_id: String,
entry: LogEntry,
},
Diagnostic {
session_id: String,
diagnostic: DiagnosticRecord,
},
ArtifactBuilt {
session_id: String,
artifact: ArtifactRecord,
},
SessionFinished(SessionFinished),
ProcessDetected(DetectedProcess),
ProcessUpdated(DetectedProcess),
ProcessGone {
session_id: String,
pid: u32,
observed_at: OffsetDateTime,
},
}