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 pub env_vars: Vec<String>,
54}
55
56impl From<&HistoryJob> for UiJobResources {
57 fn from(job: &HistoryJob) -> Self {
58 Self {
59 artifact_dir: job.artifact_dir.clone(),
60 artifact_paths: job.artifacts.clone(),
61 caches: job.caches.clone(),
62 container_name: job.container_name.clone(),
63 service_network: job.service_network.clone(),
64 service_containers: job.service_containers.clone(),
65 runtime_summary_path: job.runtime_summary_path.clone(),
66 env_vars: job.env_vars.clone(),
67 }
68 }
69}
70
71#[derive(Clone)]
72pub enum UiCommand {
73 RestartJob { name: String },
74 StartManual { name: String },
75 CancelJob { name: String },
76 AnalyzeJob { name: String, source_name: String },
77 PreviewAiPrompt { name: String, source_name: String },
78 AbortPipeline,
79}
80
81#[derive(Clone)]
82pub enum UiEvent {
83 JobStarted {
84 name: String,
85 },
86 JobRestarted {
87 name: String,
88 },
89 JobLog {
90 name: String,
91 line: String,
92 },
93 JobFinished {
94 name: String,
95 status: UiJobStatus,
96 duration: f32,
97 error: Option<String>,
98 },
99 JobManual {
100 name: String,
101 },
102 HistoryUpdated {
103 entry: HistoryEntry,
104 },
105 AnalysisStarted {
106 name: String,
107 provider: String,
108 },
109 AnalysisChunk {
110 name: String,
111 delta: String,
112 },
113 AnalysisFinished {
114 name: String,
115 final_text: String,
116 saved_path: Option<PathBuf>,
117 error: Option<String>,
118 },
119 AiPromptReady {
120 name: String,
121 prompt: String,
122 },
123 PipelineFinished,
124}
125
126#[derive(Clone, Copy, PartialEq, Eq)]
127pub enum UiJobStatus {
128 Pending,
129 Running,
130 Success,
131 Failed,
132 Skipped,
133}
134
135impl UiJobStatus {
136 pub fn is_finished(self) -> bool {
137 matches!(
138 self,
139 UiJobStatus::Success | UiJobStatus::Failed | UiJobStatus::Skipped
140 )
141 }
142
143 pub fn is_restartable(self) -> bool {
144 matches!(self, UiJobStatus::Success | UiJobStatus::Failed)
145 }
146
147 pub fn label(self) -> &'static str {
148 match self {
149 UiJobStatus::Pending => "pending",
150 UiJobStatus::Running => "running",
151 UiJobStatus::Success => "success",
152 UiJobStatus::Failed => "failed",
153 UiJobStatus::Skipped => "skipped",
154 }
155 }
156
157 pub fn from_history(status: HistoryStatus) -> Self {
158 match status {
159 HistoryStatus::Success => UiJobStatus::Success,
160 HistoryStatus::Failed => UiJobStatus::Failed,
161 HistoryStatus::Skipped => UiJobStatus::Skipped,
162 HistoryStatus::Running => UiJobStatus::Running,
163 }
164 }
165}