This commit is contained in:
Alex Emmet 2026-05-21 13:55:49 +02:00
commit 49a436da7f
3 changed files with 80 additions and 1 deletions

View file

@ -7,6 +7,7 @@ pub enum ToDoStatus {
InProgress,
Completed,
Blocked,
ReadyForAgent,
}
impl Default for ToDoStatus {
@ -22,6 +23,7 @@ impl fmt::Display for ToDoStatus {
ToDoStatus::InProgress => write!(f, "in_progress"),
ToDoStatus::Completed => write!(f, "completed"),
ToDoStatus::Blocked => write!(f, "blocked"),
ToDoStatus::ReadyForAgent => write!(f, "ready_for_agent"),
}
}
}
@ -34,6 +36,7 @@ impl std::str::FromStr for ToDoStatus {
"in_progress" => Ok(ToDoStatus::InProgress),
"completed" => Ok(ToDoStatus::Completed),
"blocked" => Ok(ToDoStatus::Blocked),
"ready_for_agent" => Ok(ToDoStatus::ReadyForAgent),
_ => Err(format!("unknown status: {}", s)),
}
}

View file

@ -17,6 +17,7 @@ pub struct Task {
pub logs: Vec<String>,
pub started_at: Option<DateTime<Utc>>,
pub completed_at: Option<DateTime<Utc>>,
pub payload: Option<serde_json::Value>,
}
impl Default for Task {
@ -32,6 +33,7 @@ impl Default for Task {
logs: Vec::new(),
started_at: None,
completed_at: None,
payload: None,
}
}
}
@ -49,9 +51,15 @@ impl Task {
logs: Vec::new(),
started_at: None,
completed_at: None,
payload: None,
}
}
pub fn with_payload<T: Serialize>(mut self, payload: &T) -> Self {
self.payload = serde_json::to_value(payload).ok();
self
}
pub fn start(&mut self) -> Result<(), String> {
match self.status {
TaskStatus::Pending => {
@ -133,6 +141,68 @@ impl TaskResult {
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestCase {
pub name: String,
pub command: String,
pub expected_output: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceLimits {
pub cpu_cores: f32,
pub memory_mb: u64,
pub gpu_memory_mb: Option<u64>,
pub timeout_seconds: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileRange {
pub path: String,
pub line_start: u32,
pub line_end: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentTaskSpec {
pub task_id: Uuid,
pub title: String,
pub description: String,
pub board_snapshot: serde_json::Value,
pub assembled_context_id: Uuid,
pub selected_files: Vec<FileRange>,
pub entry_points: Vec<String>,
pub tests: Option<Vec<TestCase>>,
pub success_criteria: Option<String>,
pub token_budget: usize,
pub resource_limits: ResourceLimits,
pub parent_task_id: Option<Uuid>,
}
impl AgentTaskSpec {
pub fn new(task_id: Uuid, title: String, assembled_context_id: Uuid) -> Self {
Self {
task_id,
title,
description: String::new(),
board_snapshot: serde_json::json!({}),
assembled_context_id,
selected_files: Vec::new(),
entry_points: Vec::new(),
tests: None,
success_criteria: None,
token_budget: 1000000, // Default 1M tokens
resource_limits: ResourceLimits {
cpu_cores: 1.0,
memory_mb: 2048,
gpu_memory_mb: None,
timeout_seconds: 3600, // 1 hour
},
parent_task_id: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -101,12 +101,18 @@ impl ToDo {
let valid_transition = match (&self.status, &status) {
(ToDoStatus::Pending, ToDoStatus::InProgress) => true,
(ToDoStatus::Pending, ToDoStatus::Blocked) => true,
(ToDoStatus::Pending, ToDoStatus::ReadyForAgent) => true,
(ToDoStatus::InProgress, ToDoStatus::Completed) => true,
(ToDoStatus::InProgress, ToDoStatus::Blocked) => true,
(ToDoStatus::InProgress, ToDoStatus::ReadyForAgent) => true,
(ToDoStatus::Blocked, ToDoStatus::InProgress) => true,
(ToDoStatus::Blocked, ToDoStatus::Pending) => true,
(ToDoStatus::Blocked, ToDoStatus::ReadyForAgent) => true,
(ToDoStatus::Completed, ToDoStatus::InProgress) => true,
_ => false,
(ToDoStatus::ReadyForAgent, ToDoStatus::InProgress) => true,
(ToDoStatus::ReadyForAgent, ToDoStatus::Pending) => true,
(ToDoStatus::ReadyForAgent, ToDoStatus::Blocked) => true,
_ => self.status == status,
};
if !valid_transition {