use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Worker {
pub id: String,
pub tags: Vec<String>,
pub max_claims: i32,
pub registered_at: i64,
pub last_heartbeat: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkerInfo {
pub id: String,
pub tags: Vec<String>,
pub max_claims: i32,
pub claim_count: i32,
pub current_thought: Option<String>,
pub registered_at: i64,
pub last_heartbeat: i64,
}
pub type Priority = i32;
pub const PRIORITY_DEFAULT: Priority = 5;
pub fn parse_priority(s: &str) -> Priority {
s.parse().unwrap_or(PRIORITY_DEFAULT).clamp(0, 10)
}
pub fn clamp_priority(p: Priority) -> Priority {
p.clamp(0, 10)
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Task {
pub id: String,
pub title: String,
pub description: Option<String>,
pub status: String,
pub priority: Priority,
pub worker_id: Option<String>,
pub claimed_at: Option<i64>,
pub needed_tags: Vec<String>,
pub wanted_tags: Vec<String>,
pub tags: Vec<String>,
pub points: Option<i32>,
pub time_estimate_ms: Option<i64>,
pub time_actual_ms: Option<i64>,
pub started_at: Option<i64>,
pub completed_at: Option<i64>,
pub current_thought: Option<String>,
pub cost_usd: f64,
pub metrics: [i64; 8],
pub created_at: i64,
pub updated_at: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskTree {
#[serde(flatten)]
pub task: Task,
pub children: Vec<TaskTree>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskTreeInput {
#[serde(rename = "ref")]
pub ref_id: Option<String>,
pub id: Option<String>,
#[serde(default)]
pub title: String,
pub description: Option<String>,
pub priority: Option<Priority>,
pub points: Option<i32>,
pub time_estimate_ms: Option<i64>,
pub needed_tags: Option<Vec<String>>,
pub wanted_tags: Option<Vec<String>>,
pub tags: Option<Vec<String>>,
#[serde(default)]
pub children: Vec<TaskTreeInput>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Dependency {
pub from_task_id: String,
pub to_task_id: String,
pub dep_type: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileLock {
pub file_path: String,
pub worker_id: String,
pub reason: Option<String>,
pub locked_at: i64,
pub task_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClaimEvent {
pub id: i64,
pub file_path: String,
pub worker_id: String,
pub event: ClaimEventType,
pub reason: Option<String>,
pub timestamp: i64,
pub end_timestamp: Option<i64>,
pub claim_id: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskStateEvent {
pub id: i64,
pub task_id: String,
pub worker_id: Option<String>,
pub event: String,
pub reason: Option<String>,
pub timestamp: i64,
pub end_timestamp: Option<i64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ClaimEventType {
Claimed,
Released,
}
impl ClaimEventType {
pub fn as_str(&self) -> &'static str {
match self {
ClaimEventType::Claimed => "claimed",
ClaimEventType::Released => "released",
}
}
pub fn from_str(s: &str) -> Option<Self> {
match s {
"claimed" => Some(ClaimEventType::Claimed),
"released" => Some(ClaimEventType::Released),
_ => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClaimUpdates {
pub new_claims: Vec<ClaimEvent>,
pub dropped_claims: Vec<ClaimEvent>,
pub sequence: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Attachment {
pub task_id: String,
pub order_index: i32,
pub name: String,
pub mime_type: String,
pub content: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_path: Option<String>,
pub created_at: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttachmentMeta {
pub task_id: String,
pub order_index: i32,
pub name: String,
pub mime_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_path: Option<String>,
pub created_at: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Stats {
pub total_tasks: i64,
pub tasks_by_status: HashMap<String, i64>,
pub total_points: i64,
pub completed_points: i64,
pub total_time_estimate_ms: i64,
pub total_time_actual_ms: i64,
pub total_cost_usd: f64,
pub total_metrics: [i64; 8],
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskSummary {
pub id: String,
pub title: String,
pub status: String,
pub priority: Priority,
pub worker_id: Option<String>,
pub points: Option<i32>,
pub current_thought: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScanResult {
pub root: Task,
pub before: Vec<Task>,
pub after: Vec<Task>,
pub above: Vec<Task>,
pub below: Vec<Task>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DisconnectSummary {
pub tasks_released: i32,
pub files_released: i32,
pub final_status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanupSummary {
pub workers_evicted: i32,
pub tasks_released: i32,
pub files_released: i32,
pub final_status: String,
pub evicted_worker_ids: Vec<String>,
}
#[cfg(test)]
mod tests {
}