1use crate::history::{HistoryCache, HistoryEntry, HistoryJob, HistoryStatus};
2use std::path::PathBuf;
3
4pub const LOG_SCROLL_STEP: usize = 3;
5pub const LOG_SCROLL_HALF: usize = 20;
6pub const LOG_SCROLL_PAGE: usize = 60;
7pub const CURRENT_HISTORY_KEY: &str = "__current_run__";
8
9#[derive(Clone, Copy, PartialEq, Eq)]
10pub enum PaneFocus {
11 History,
12 Jobs,
13 JobYaml,
14}
15
16#[derive(Clone)]
17pub enum HistoryAction {
18 SelectJob(usize),
19 ViewLog { title: String, path: PathBuf },
20 ViewRun(String),
21 ViewHistoryJob { run_id: String, job_name: String },
22 ViewDir { title: String, path: PathBuf },
23 ViewFile { title: String, path: PathBuf },
24}
25
26#[derive(Clone)]
27pub struct UiJobInfo {
28 pub name: String,
29 pub source_name: String,
30 pub stage: String,
31 pub log_path: PathBuf,
32 pub log_hash: String,
33 pub runner: UiRunnerInfo,
34}
35
36#[derive(Clone, Default)]
37pub struct UiRunnerInfo {
38 pub engine: String,
39 pub arch: Option<String>,
40 pub cpus: Option<String>,
41 pub memory: Option<String>,
42}
43
44#[derive(Clone, Default)]
45pub struct UiJobResources {
46 pub artifact_dir: Option<String>,
47 pub artifact_paths: Vec<String>,
48 pub caches: Vec<HistoryCache>,
49 pub container_name: Option<String>,
50 pub service_network: Option<String>,
51 pub service_containers: Vec<String>,
52 pub runtime_summary_path: Option<String>,
53}
54
55impl From<&HistoryJob> for UiJobResources {
56 fn from(job: &HistoryJob) -> Self {
57 Self {
58 artifact_dir: job.artifact_dir.clone(),
59 artifact_paths: job.artifacts.clone(),
60 caches: job.caches.clone(),
61 container_name: job.container_name.clone(),
62 service_network: job.service_network.clone(),
63 service_containers: job.service_containers.clone(),
64 runtime_summary_path: job.runtime_summary_path.clone(),
65 }
66 }
67}
68
69#[derive(Clone)]
70pub enum UiCommand {
71 RestartJob { name: String },
72 StartManual { name: String },
73 CancelJob { name: String },
74 AnalyzeJob { name: String, source_name: String },
75 PreviewAiPrompt { name: String, source_name: String },
76 AbortPipeline,
77}
78
79#[derive(Clone)]
80pub enum UiEvent {
81 JobStarted {
82 name: String,
83 },
84 JobRestarted {
85 name: String,
86 },
87 JobLog {
88 name: String,
89 line: String,
90 },
91 JobFinished {
92 name: String,
93 status: UiJobStatus,
94 duration: f32,
95 error: Option<String>,
96 },
97 JobManual {
98 name: String,
99 },
100 HistoryUpdated {
101 entry: HistoryEntry,
102 },
103 AnalysisStarted {
104 name: String,
105 provider: String,
106 },
107 AnalysisChunk {
108 name: String,
109 delta: String,
110 },
111 AnalysisFinished {
112 name: String,
113 final_text: String,
114 saved_path: Option<PathBuf>,
115 error: Option<String>,
116 },
117 AiPromptReady {
118 name: String,
119 prompt: String,
120 },
121 PipelineFinished,
122}
123
124#[derive(Clone, Copy, PartialEq, Eq)]
125pub enum UiJobStatus {
126 Pending,
127 Running,
128 Success,
129 Failed,
130 Skipped,
131}
132
133impl UiJobStatus {
134 pub fn is_finished(self) -> bool {
135 matches!(
136 self,
137 UiJobStatus::Success | UiJobStatus::Failed | UiJobStatus::Skipped
138 )
139 }
140
141 pub fn is_restartable(self) -> bool {
142 matches!(self, UiJobStatus::Success | UiJobStatus::Failed)
143 }
144
145 pub fn label(self) -> &'static str {
146 match self {
147 UiJobStatus::Pending => "pending",
148 UiJobStatus::Running => "running",
149 UiJobStatus::Success => "success",
150 UiJobStatus::Failed => "failed",
151 UiJobStatus::Skipped => "skipped",
152 }
153 }
154
155 pub fn from_history(status: HistoryStatus) -> Self {
156 match status {
157 HistoryStatus::Success => UiJobStatus::Success,
158 HistoryStatus::Failed => UiJobStatus::Failed,
159 HistoryStatus::Skipped => UiJobStatus::Skipped,
160 HistoryStatus::Running => UiJobStatus::Running,
161 }
162 }
163}