Task 1.1: ✅ Cargo.toml with axum, rusqlite, matrix-sdk, serde, etc. Task 1.2: ✅ Directory structure: src/core, src/adapters, src/integrations, src/api Task 1.5: ✅ config.example.toml with full schema Task 2.1: ✅ Data models: Agent, Task, Receipt, Artifact, TaskEvent Task 2.2: ✅ Event Store: SQLite append-only with task/agent tables Task 2.3: ✅ Task state machine: created→assigned→running→completed/failed Task 2.4: ✅ Global task queue with priority ordering Task 2.5: ✅ Background timeout checker Task 2.6: ✅ Retry policy with configurable max_retries Compiles clean (warnings only, no errors). API handler stubs in place for Phase 2.
145 lines
4 KiB
Rust
145 lines
4 KiB
Rust
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
// ─── Agent ───────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
#[serde(rename_all = "kebab-case")]
|
|
pub enum AgentType {
|
|
OpenClaw,
|
|
ClaudeCode,
|
|
CodexCli,
|
|
Hermes,
|
|
Acp,
|
|
Shell,
|
|
Other(String),
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum AgentStatus {
|
|
Online,
|
|
Offline,
|
|
Draining,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Agent {
|
|
pub agent_id: String,
|
|
pub agent_type: AgentType,
|
|
pub hostname: String,
|
|
pub capabilities: Vec<String>,
|
|
pub max_concurrency: u32,
|
|
pub current_tasks: u32,
|
|
pub status: AgentStatus,
|
|
pub last_heartbeat_at: DateTime<Utc>,
|
|
pub registered_at: DateTime<Utc>,
|
|
pub metadata: std::collections::HashMap<String, String>,
|
|
}
|
|
|
|
// ─── Task ────────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum TaskStatus {
|
|
Created,
|
|
Assigned,
|
|
Running,
|
|
Completed,
|
|
Failed,
|
|
AgentLost,
|
|
Cancelled,
|
|
}
|
|
|
|
impl TaskStatus {
|
|
pub fn as_str(&self) -> &'static str {
|
|
match self {
|
|
Self::Created => "created",
|
|
Self::Assigned => "assigned",
|
|
Self::Running => "running",
|
|
Self::Completed => "completed",
|
|
Self::Failed => "failed",
|
|
Self::AgentLost => "agent_lost",
|
|
Self::Cancelled => "cancelled",
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum Priority {
|
|
Low,
|
|
Normal,
|
|
High,
|
|
Urgent,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Task {
|
|
pub task_id: String,
|
|
pub source: String, // "forgejo:<repo>#<issue>"
|
|
pub task_type: String, // "code", "review", "test", "deploy", "research"
|
|
pub priority: Priority,
|
|
pub status: TaskStatus,
|
|
pub assigned_agent_id: Option<String>,
|
|
pub requirements: String, // Issue body
|
|
pub labels: Vec<String>,
|
|
pub created_at: DateTime<Utc>,
|
|
pub assigned_at: Option<DateTime<Utc>>,
|
|
pub started_at: Option<DateTime<Utc>>,
|
|
pub completed_at: Option<DateTime<Utc>>,
|
|
pub retry_count: u32,
|
|
pub max_retries: u32,
|
|
pub timeout_seconds: u64,
|
|
}
|
|
|
|
// ─── Receipt ─────────────────────────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum ReceiptStatus {
|
|
Completed,
|
|
Failed,
|
|
Partial,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum ArtifactType {
|
|
Pr,
|
|
Commit,
|
|
File,
|
|
Comment,
|
|
Url,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Artifact {
|
|
pub artifact_type: ArtifactType,
|
|
pub url: Option<String>,
|
|
pub path: Option<String>,
|
|
pub description: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Receipt {
|
|
pub task_id: String,
|
|
pub agent_id: String,
|
|
pub status: ReceiptStatus,
|
|
pub duration_seconds: u64,
|
|
pub summary: String,
|
|
pub artifacts: Vec<Artifact>,
|
|
pub error: Option<String>,
|
|
}
|
|
|
|
// ─── TaskEvent (event sourcing) ──────────────────────────────────
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct TaskEvent {
|
|
pub event_id: String,
|
|
pub task_id: String,
|
|
pub event_type: String,
|
|
pub agent_id: Option<String>,
|
|
pub timestamp: DateTime<Utc>,
|
|
pub payload: serde_json::Value,
|
|
}
|