1use serde::{Deserialize, Serialize};
11use std::path::PathBuf;
12
13pub use observation::{
16 ChunkRef, Diagnostic, Event, EventScope, EventSource, ForgeId, Level, TaskRunId,
17 RESERVED_FIELD_PATHS,
18};
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
23#[serde(tag = "status", rename_all = "snake_case")]
24pub enum RunStatus {
25 Pending,
26 Running,
27 Done { exit_code: i32, ended_at: u64 },
28 Killed { signal: i32, ended_at: u64 },
29 Lost { reason: String },
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
35#[serde(tag = "kind", rename_all = "snake_case")]
36pub enum Initiator {
37 Human { camp: String },
38 Agent { camp: String, agent: String, session: String },
39 Gnome { camp: String, shift: String },
40 Cron { camp: String, schedule: String },
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct BeholderStatus {
52 pub text: String,
53 #[serde(skip_serializing_if = "Option::is_none")]
56 pub rewrite_added: Option<Vec<String>>,
57}
58
59impl BeholderStatus {
60 fn make(text: String) -> Self {
61 Self { text, rewrite_added: None }
62 }
63
64 pub fn none_auto() -> Self {
65 Self::make("none:auto".to_string())
66 }
67 pub fn none_explicit() -> Self {
69 Self::make("none:explicit".to_string())
70 }
71 pub fn attached(name: &str, version: &str) -> Self {
72 Self::make(format!("attached:{name}@{version}"))
73 }
74 pub fn declined(name: &str, reason: &str) -> Self {
75 Self::make(format!("declined:{name} reason=\"{reason}\""))
76 }
77 pub fn forced(name: &str, version: &str) -> Self {
79 Self::make(format!("forced:{name}@{version}"))
80 }
81 pub fn forced_against_flags(name: &str, version: &str) -> Self {
83 Self::make(format!("forced-against-flags:{name}@{version}"))
84 }
85 pub fn forced_against_tty(name: &str, version: &str) -> Self {
88 Self::make(format!("forced-against-tty:{name}@{version}"))
89 }
90 pub fn unknown_format() -> Self {
91 Self::make("unknown_format".to_string())
92 }
93 pub fn unknown_format_with_reason(name: &str, reason: &str) -> Self {
96 Self::make(format!("unknown_format:{name} reason=\"{reason}\""))
97 }
98
99 pub fn with_rewrite(mut self, added: Vec<String>) -> Self {
104 if !added.is_empty() {
105 let repr = added.join(" ");
106 self.text = format!("{} rewrite=\"{repr}\"", self.text);
107 self.rewrite_added = Some(added);
108 }
109 self
110 }
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct TaskRunMeta {
117 pub id: TaskRunId,
118 pub command: String,
119 pub cwd: PathBuf,
120 pub env: Vec<(String, String)>,
121 pub started_at: u64,
122 pub status: RunStatus,
123 pub label: Option<String>,
124 pub initiator: Initiator,
125 pub beholder_status: Option<BeholderStatus>,
126 #[serde(default)]
129 pub pinned: bool,
130 #[serde(default)]
136 pub origin: Option<String>,
137}
138
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
142#[serde(rename_all = "lowercase")]
143pub enum Stream {
144 Stdout,
145 Stderr,
146 Synth,
147}
148
149impl Stream {
150 pub fn as_str(self) -> &'static str {
151 match self {
152 Stream::Stdout => "stdout",
153 Stream::Stderr => "stderr",
154 Stream::Synth => "synth",
155 }
156 }
157}
158
159impl std::str::FromStr for Stream {
160 type Err = String;
161 fn from_str(s: &str) -> Result<Self, Self::Err> {
162 match s {
163 "stdout" => Ok(Stream::Stdout),
164 "stderr" => Ok(Stream::Stderr),
165 "synth" => Ok(Stream::Synth),
166 other => Err(format!("unknown stream: {other}")),
167 }
168 }
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct OutputChunk {
175 pub run_id: TaskRunId,
176 pub seq: u32,
177 pub offset_ms: u32,
178 pub stream: Stream,
179 pub bytes: Vec<u8>,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct SeqRange {
187 pub lo: u32,
188 pub hi: u32,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct Triage {
201 pub run_id: TaskRunId,
202 pub synopsis: String,
203 pub keep: Vec<KeepRange>,
204 pub primary: SeqRange,
205 pub model: String,
206 pub prompt_version: u32,
207 pub cached_at: u64,
208 pub partial: bool,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize)]
212pub struct KeepRange {
213 pub range: SeqRange,
214 pub reason: String,
215}