155 lines
4.3 KiB
Rust
155 lines
4.3 KiB
Rust
//! Agent task model — sub-agents and sub-tasks as a unified concept.
|
|
//!
|
|
//! An `agent_task` represents either:
|
|
//! - A **root task** (parent_id = NULL): initiated by a user or system event.
|
|
//! The parent agent (Supervisor) spawns sub-tasks and coordinates their results.
|
|
//! - A **sub-task** (parent_id = set): a unit of work executed by a sub-agent.
|
|
//!
|
|
//! Status lifecycle: `pending` → `running` → `done` | `failed`
|
|
//!
|
|
//! Sub-agents are represented as `agent_task` records with a parent reference,
|
|
//! allowing hierarchical task trees and result aggregation.
|
|
|
|
use crate::{DateTimeUtc, ProjectId, UserId};
|
|
use sea_orm::entity::prelude::*;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// Agent task type — the kind of agent that executes this task.
|
|
#[derive(
|
|
Clone, Debug, PartialEq, Eq, EnumIter, Serialize, Deserialize, sea_orm::DeriveActiveEnum,
|
|
)]
|
|
#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
|
|
pub enum AgentType {
|
|
#[sea_orm(string_value = "React")]
|
|
React,
|
|
#[sea_orm(string_value = "Chat")]
|
|
Chat,
|
|
}
|
|
|
|
impl Default for AgentType {
|
|
fn default() -> Self {
|
|
AgentType::React
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for AgentType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
AgentType::React => write!(f, "React"),
|
|
AgentType::Chat => write!(f, "Chat"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Task status lifecycle.
|
|
#[derive(
|
|
Clone, Debug, PartialEq, Eq, EnumIter, Serialize, Deserialize, sea_orm::DeriveActiveEnum,
|
|
)]
|
|
#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
|
|
pub enum TaskStatus {
|
|
#[sea_orm(string_value = "Pending")]
|
|
Pending,
|
|
#[sea_orm(string_value = "Running")]
|
|
Running,
|
|
#[sea_orm(string_value = "Done")]
|
|
Done,
|
|
#[sea_orm(string_value = "Failed")]
|
|
Failed,
|
|
}
|
|
|
|
impl Default for TaskStatus {
|
|
fn default() -> Self {
|
|
TaskStatus::Pending
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for TaskStatus {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
TaskStatus::Pending => write!(f, "Pending"),
|
|
TaskStatus::Running => write!(f, "Running"),
|
|
TaskStatus::Done => write!(f, "Done"),
|
|
TaskStatus::Failed => write!(f, "Failed"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Agent task record — represents both root tasks and sub-tasks.
|
|
#[derive(Clone, Debug, DeriveEntityModel, Serialize, Deserialize)]
|
|
#[sea_orm(table_name = "agent_task")]
|
|
pub struct Model {
|
|
#[sea_orm(primary_key)]
|
|
pub id: i64,
|
|
|
|
/// Project this task belongs to.
|
|
pub project_uuid: ProjectId,
|
|
|
|
/// Parent task (NULL for root tasks, set for sub-tasks).
|
|
#[sea_orm(nullable)]
|
|
pub parent_id: Option<i64>,
|
|
|
|
/// Agent type that executes this task.
|
|
#[sea_orm(column_type = "String(StringLen::None)", default = "React")]
|
|
pub agent_type: AgentType,
|
|
|
|
/// Current task status.
|
|
#[sea_orm(column_type = "String(StringLen::None)", default = "Pending")]
|
|
pub status: TaskStatus,
|
|
|
|
/// Human-readable task title / goal description.
|
|
#[sea_orm(nullable)]
|
|
pub title: Option<String>,
|
|
|
|
/// Task input — the prompt or goal text.
|
|
pub input: String,
|
|
|
|
/// Task output — populated when status = done.
|
|
#[sea_orm(nullable)]
|
|
pub output: Option<String>,
|
|
|
|
/// Error message — populated when status = failed.
|
|
#[sea_orm(nullable)]
|
|
pub error: Option<String>,
|
|
|
|
/// User who initiated this task.
|
|
#[sea_orm(nullable)]
|
|
pub created_by: Option<UserId>,
|
|
|
|
pub created_at: DateTimeUtc,
|
|
pub updated_at: DateTimeUtc,
|
|
|
|
/// When execution started (status → running).
|
|
#[sea_orm(nullable)]
|
|
pub started_at: Option<DateTimeUtc>,
|
|
|
|
/// When execution completed (status → done | failed).
|
|
#[sea_orm(nullable)]
|
|
pub done_at: Option<DateTimeUtc>,
|
|
|
|
/// Current progress description (e.g., "step 2/5: analyzing code").
|
|
#[sea_orm(nullable)]
|
|
pub progress: Option<String>,
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
|
pub enum Relation {
|
|
#[sea_orm(
|
|
belongs_to = "Entity",
|
|
from = "Column::ParentId",
|
|
to = "Column::Id"
|
|
)]
|
|
ParentTask,
|
|
}
|
|
|
|
impl ActiveModelBehavior for ActiveModel {}
|
|
|
|
impl Model {
|
|
pub fn is_root_task(&self) -> bool {
|
|
self.parent_id.is_none()
|
|
}
|
|
|
|
pub fn is_done(&self) -> bool {
|
|
matches!(self.status, TaskStatus::Done | TaskStatus::Failed)
|
|
}
|
|
}
|