1use std::fmt;
8
9use serde::{Deserialize, Serialize};
10
11use super::*;
12
13pub(crate) const SCHEMA_VERSION: i32 = 6;
25
26pub(crate) const OWNER_KIND_DAEMON: &str = "daemon";
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
35#[serde(rename_all = "snake_case")]
36pub enum TaskStatus {
37 Queued,
38 Running,
39 WaitingForApproval,
40 Blocked,
41 Completed,
42 Failed,
43 Cancelled,
44}
45
46impl TaskStatus {
47 #[must_use]
48 pub fn as_str(self) -> &'static str {
49 match self {
50 Self::Queued => "queued",
51 Self::Running => "running",
52 Self::WaitingForApproval => "waiting_for_approval",
53 Self::Blocked => "blocked",
54 Self::Completed => "completed",
55 Self::Failed => "failed",
56 Self::Cancelled => "cancelled",
57 }
58 }
59
60 pub(crate) fn from_db(value: &str) -> std::result::Result<Self, UnknownRuntimeEnum> {
61 match value {
62 "queued" => Ok(Self::Queued),
63 "running" => Ok(Self::Running),
64 "waiting_for_approval" => Ok(Self::WaitingForApproval),
65 "blocked" => Ok(Self::Blocked),
66 "completed" => Ok(Self::Completed),
67 "failed" => Ok(Self::Failed),
68 "cancelled" => Ok(Self::Cancelled),
69 other => Err(UnknownRuntimeEnum::new("task status", other)),
70 }
71 }
72}
73
74impl fmt::Display for TaskStatus {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 f.write_str(self.as_str())
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
81#[serde(rename_all = "snake_case")]
82pub enum TaskPriority {
83 Low,
84 Normal,
85 High,
86}
87
88impl TaskPriority {
89 #[must_use]
90 pub fn as_str(self) -> &'static str {
91 match self {
92 Self::Low => "low",
93 Self::Normal => "normal",
94 Self::High => "high",
95 }
96 }
97
98 pub(crate) fn from_db(value: &str) -> std::result::Result<Self, UnknownRuntimeEnum> {
99 match value {
100 "low" => Ok(Self::Low),
101 "normal" => Ok(Self::Normal),
102 "high" => Ok(Self::High),
103 other => Err(UnknownRuntimeEnum::new("task priority", other)),
104 }
105 }
106}
107
108impl fmt::Display for TaskPriority {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 f.write_str(self.as_str())
111 }
112}
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
115#[serde(rename_all = "snake_case")]
116pub enum ProcessStatus {
117 Running,
118 Exited,
119 Unknown,
120}
121
122impl ProcessStatus {
123 #[must_use]
124 pub fn as_str(self) -> &'static str {
125 match self {
126 Self::Running => "running",
127 Self::Exited => "exited",
128 Self::Unknown => "unknown",
129 }
130 }
131
132 pub(crate) fn from_db(value: &str) -> std::result::Result<Self, UnknownRuntimeEnum> {
133 match value {
134 "running" => Ok(Self::Running),
135 "exited" => Ok(Self::Exited),
136 "unknown" => Ok(Self::Unknown),
137 other => Err(UnknownRuntimeEnum::new("process status", other)),
138 }
139 }
140}
141
142#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
143pub struct TaskRecord {
144 pub id: String,
145 pub title: String,
146 pub status: TaskStatus,
147 pub priority: TaskPriority,
148 pub project_path: String,
149 pub model_id: String,
150 pub conversation_id: Option<String>,
151 pub created_at: String,
152 pub updated_at: String,
153 pub final_report: Option<String>,
154 pub prompt: Option<String>,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
161pub struct TaskTimelineEvent {
162 pub id: i64,
163 pub task_id: String,
164 pub kind: String,
165 pub message: String,
166 pub created_at: String,
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
170pub struct SessionRecord {
171 pub id: String,
172 pub project_path: String,
173 pub model_id: String,
174 pub title: Option<String>,
175 pub conversation_path: Option<String>,
176 pub created_at: String,
177 pub updated_at: String,
178 pub total_tokens: Option<i64>,
179}
180
181#[derive(Debug, Clone, PartialEq, Eq)]
182pub struct NewSession {
183 pub id: Option<String>,
184 pub project_path: String,
185 pub model_id: String,
186 pub title: Option<String>,
187 pub conversation_path: Option<String>,
188 pub total_tokens: Option<i64>,
189}
190
191#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
192pub struct MessageRecord {
193 pub id: i64,
194 pub session_id: String,
195 pub role: String,
196 pub content_json: String,
197 pub created_at: String,
198}
199
200#[derive(Debug, Clone, PartialEq, Eq)]
201pub struct NewMessage {
202 pub session_id: String,
203 pub role: String,
204 pub content_json: String,
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub struct NewTask {
209 pub title: String,
210 pub project_path: String,
211 pub model_id: String,
212 pub priority: TaskPriority,
213 pub conversation_id: Option<String>,
214 pub owner_kind: Option<String>,
220 pub prompt: Option<String>,
223}
224
225impl NewTask {
226 pub fn new(
227 title: impl Into<String>,
228 project_path: impl Into<String>,
229 model_id: impl Into<String>,
230 ) -> Self {
231 Self {
232 title: title.into(),
233 project_path: project_path.into(),
234 model_id: model_id.into(),
235 priority: TaskPriority::Normal,
236 conversation_id: None,
237 owner_kind: None,
238 prompt: None,
239 }
240 }
241
242 #[must_use]
246 pub fn daemon_owned(mut self) -> Self {
247 self.owner_kind = Some(OWNER_KIND_DAEMON.to_string());
248 self
249 }
250
251 pub fn with_prompt(mut self, prompt: impl Into<String>) -> Self {
253 self.prompt = Some(prompt.into());
254 self
255 }
256
257 #[must_use]
258 pub fn with_priority(mut self, priority: TaskPriority) -> Self {
259 self.priority = priority;
260 self
261 }
262}
263
264#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
265pub struct ApprovalRecord {
266 pub id: String,
267 pub task_id: Option<String>,
268 pub proposed_action: String,
269 pub risk_classification: String,
270 pub policy_decision: String,
271 pub user_decision: Option<String>,
272 pub args_summary: Option<String>,
273 pub checkpoint_id: Option<String>,
274 pub pending_action_json: Option<String>,
275 pub created_at: String,
276 pub decided_at: Option<String>,
277 pub archived_at: Option<String>,
278 pub archive_reason: Option<String>,
279}
280
281#[derive(Debug, Clone, PartialEq, Eq)]
282pub struct NewApproval {
283 pub task_id: Option<String>,
284 pub proposed_action: String,
285 pub risk_classification: String,
286 pub policy_decision: String,
287 pub args_summary: Option<String>,
288 pub checkpoint_id: Option<String>,
289 pub pending_action_json: Option<String>,
290}
291
292#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
293pub struct ToolRunRecord {
294 pub id: String,
295 pub task_id: Option<String>,
296 pub turn_id: Option<String>,
297 pub call_id: Option<String>,
298 pub tool_name: String,
299 pub status: String,
300 pub args_json: Option<String>,
301 pub output_json: Option<String>,
302 pub started_at: String,
303 pub finished_at: Option<String>,
304}
305
306#[derive(Debug, Clone, PartialEq, Eq)]
307pub struct NewToolRun {
308 pub id: Option<String>,
309 pub task_id: Option<String>,
310 pub turn_id: Option<String>,
311 pub call_id: Option<String>,
312 pub tool_name: String,
313 pub args_json: Option<String>,
314}
315
316#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
317pub struct ProcessRecord {
318 pub id: String,
319 pub task_id: Option<String>,
320 pub pid: u32,
321 pub command: String,
322 pub cwd: Option<String>,
323 pub log_path: Option<String>,
324 pub detected_url: Option<String>,
325 pub status: ProcessStatus,
326 pub health: Option<String>,
327 pub created_at: String,
328 pub updated_at: String,
329}
330
331#[derive(Debug, Clone, PartialEq, Eq)]
332pub struct NewProcess {
333 pub id: Option<String>,
334 pub task_id: Option<String>,
335 pub pid: u32,
336 pub command: String,
337 pub cwd: Option<String>,
338 pub log_path: Option<String>,
339 pub detected_url: Option<String>,
340 pub status: ProcessStatus,
341 pub health: Option<String>,
342}
343
344#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
345pub struct CheckpointRecord {
346 pub id: String,
347 pub task_id: Option<String>,
348 pub project_path: String,
349 pub snapshot_path: String,
350 pub changed_files_json: String,
351 pub pending_action_json: Option<String>,
352 pub approval_id: Option<String>,
353 pub created_at: String,
354 pub archived_at: Option<String>,
355 pub archive_reason: Option<String>,
356 pub session_id: Option<String>,
360 pub message_index: Option<i64>,
365}
366
367#[derive(Debug, Clone, PartialEq, Eq)]
368pub struct NewCheckpoint {
369 pub id: Option<String>,
370 pub task_id: Option<String>,
371 pub project_path: String,
372 pub snapshot_path: String,
373 pub changed_files_json: String,
374 pub pending_action_json: Option<String>,
375 pub approval_id: Option<String>,
376 pub session_id: Option<String>,
377 pub message_index: Option<i64>,
378}
379
380pub const OUTCOME_SOURCE_VERIFIER: &str = "verifier";
387pub const OUTCOME_SOURCE_USER: &str = "user";
388pub const OUTCOME_SOURCE_MODEL: &str = "model";
389pub const OUTCOME_SOURCE_SYSTEM: &str = "system";
390
391pub const OUTCOME_LABEL_SUCCESS: &str = "success";
395pub const OUTCOME_LABEL_FAILURE: &str = "failure";
396pub const OUTCOME_LABEL_PARTIAL: &str = "partial";
397pub const OUTCOME_LABEL_ACCEPTED: &str = "accepted";
398pub const OUTCOME_LABEL_REJECTED: &str = "rejected";
399pub const OUTCOME_LABEL_UNKNOWN: &str = "unknown";
400
401#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
407pub struct OutcomeRecord {
408 pub id: String,
409 pub task_id: Option<String>,
410 pub tool_run_id: Option<String>,
411 pub kind: String,
414 pub label: String,
416 pub reward: Option<f64>,
419 pub source: String,
421 pub detail_json: Option<String>,
424 pub created_at: String,
425}
426
427#[derive(Debug, Clone, PartialEq)]
428pub struct NewOutcome {
429 pub id: Option<String>,
430 pub task_id: Option<String>,
431 pub tool_run_id: Option<String>,
432 pub kind: String,
433 pub label: String,
434 pub reward: Option<f64>,
435 pub source: String,
436 pub detail_json: Option<String>,
437}
438
439#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
440pub struct CompactionRecord {
441 pub id: String,
442 pub task_id: Option<String>,
443 pub session_id: Option<String>,
444 pub source_token_estimate: Option<i64>,
445 pub summary_token_count: Option<i64>,
446 pub preserved_turns: Option<i64>,
447 pub archive_path: Option<String>,
448 pub verification_status: Option<String>,
449 pub created_at: String,
450}
451
452#[derive(Debug, Clone, PartialEq, Eq)]
453pub struct NewCompaction {
454 pub id: Option<String>,
455 pub task_id: Option<String>,
456 pub session_id: Option<String>,
457 pub source_token_estimate: Option<i64>,
458 pub summary_token_count: Option<i64>,
459 pub preserved_turns: Option<i64>,
460 pub archive_path: Option<String>,
461 pub verification_status: Option<String>,
462}
463
464#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
465pub struct PluginInstallRecord {
466 pub id: String,
467 pub name: String,
468 pub source: String,
469 pub version: Option<String>,
470 pub enabled: bool,
471 pub manifest_json: String,
472 pub installed_at: String,
473 pub updated_at: String,
474}
475
476#[derive(Debug, Clone, PartialEq, Eq)]
477pub struct NewPluginInstall {
478 pub id: Option<String>,
479 pub name: String,
480 pub source: String,
481 pub version: Option<String>,
482 pub enabled: bool,
483 pub manifest_json: String,
484}
485
486#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
487pub struct ProviderProbeRecord {
488 pub provider: String,
489 pub model_id: String,
490 pub capability_key: String,
491 pub capability_value: String,
492 pub confidence: String,
493 pub error: Option<String>,
494 pub probed_at: String,
495}
496
497#[derive(Debug, Clone, PartialEq, Eq)]
498pub struct NewProviderProbe {
499 pub provider: String,
500 pub model_id: String,
501 pub capability_key: String,
502 pub capability_value: String,
503 pub confidence: String,
504 pub error: Option<String>,
505}
506
507#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
508pub struct PairingTokenRecord {
509 pub id: String,
510 pub token_hash: String,
511 pub label: Option<String>,
512 pub enabled: bool,
513 pub created_at: String,
514 pub last_used_at: Option<String>,
515 pub expires_at: Option<String>,
517}