| use chrono::DateTime; |
| use chrono::Utc; |
| use serde::Deserialize; |
| use serde::Serialize; |
| use std::future::Future; |
| use std::pin::Pin; |
|
|
| pub type Result<T> = std::result::Result<T, CloudTaskError>; |
| pub type CloudBackendFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T>> + Send + 'a>>; |
|
|
| #[derive(Debug, thiserror::Error)] |
| pub enum CloudTaskError { |
| #[error("unimplemented: {0}")] |
| Unimplemented(&'static str), |
| #[error("http error: {0}")] |
| Http(String), |
| #[error("io error: {0}")] |
| Io(String), |
| #[error("{0}")] |
| Msg(String), |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
| #[serde(transparent)] |
| pub struct TaskId(pub String); |
|
|
| #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
| #[serde(rename_all = "kebab-case")] |
| pub enum TaskStatus { |
| Pending, |
| Ready, |
| Applied, |
| Error, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
| pub struct TaskSummary { |
| pub id: TaskId, |
| pub title: String, |
| pub status: TaskStatus, |
| pub updated_at: DateTime<Utc>, |
| |
| pub environment_id: Option<String>, |
| |
| pub environment_label: Option<String>, |
| pub summary: DiffSummary, |
| |
| #[serde(default)] |
| pub is_review: bool, |
| |
| #[serde(default)] |
| pub attempt_total: Option<usize>, |
| } |
|
|
| #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] |
| pub enum AttemptStatus { |
| Pending, |
| InProgress, |
| Completed, |
| Failed, |
| Cancelled, |
| #[default] |
| Unknown, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq)] |
| pub struct TurnAttempt { |
| pub turn_id: String, |
| pub attempt_placement: Option<i64>, |
| pub created_at: Option<DateTime<Utc>>, |
| pub status: AttemptStatus, |
| pub diff: Option<String>, |
| pub messages: Vec<String>, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
| #[serde(rename_all = "lowercase")] |
| pub enum ApplyStatus { |
| Success, |
| Partial, |
| Error, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
| pub struct ApplyOutcome { |
| pub applied: bool, |
| pub status: ApplyStatus, |
| pub message: String, |
| #[serde(default)] |
| pub skipped_paths: Vec<String>, |
| #[serde(default)] |
| pub conflict_paths: Vec<String>, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
| pub struct CreatedTask { |
| pub id: TaskId, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq)] |
| pub struct TaskListPage { |
| pub tasks: Vec<TaskSummary>, |
| pub cursor: Option<String>, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] |
| pub struct DiffSummary { |
| pub files_changed: usize, |
| pub lines_added: usize, |
| pub lines_removed: usize, |
| } |
|
|
| #[derive(Clone, Debug, PartialEq, Eq)] |
| pub struct TaskText { |
| pub prompt: Option<String>, |
| pub messages: Vec<String>, |
| pub turn_id: Option<String>, |
| pub sibling_turn_ids: Vec<String>, |
| pub attempt_placement: Option<i64>, |
| pub attempt_status: AttemptStatus, |
| } |
|
|
| impl Default for TaskText { |
| fn default() -> Self { |
| Self { |
| prompt: None, |
| messages: Vec::new(), |
| turn_id: None, |
| sibling_turn_ids: Vec::new(), |
| attempt_placement: None, |
| attempt_status: AttemptStatus::Unknown, |
| } |
| } |
| } |
|
|
| pub trait CloudBackend: Send + Sync { |
| fn list_tasks<'a>( |
| &'a self, |
| env: Option<&'a str>, |
| limit: Option<i64>, |
| cursor: Option<&'a str>, |
| ) -> CloudBackendFuture<'a, TaskListPage>; |
| fn get_task_summary(&self, id: TaskId) -> CloudBackendFuture<'_, TaskSummary>; |
| fn get_task_diff(&self, id: TaskId) -> CloudBackendFuture<'_, Option<String>>; |
| |
| fn get_task_messages(&self, id: TaskId) -> CloudBackendFuture<'_, Vec<String>>; |
| |
| fn get_task_text(&self, id: TaskId) -> CloudBackendFuture<'_, TaskText>; |
| |
| fn list_sibling_attempts( |
| &self, |
| task: TaskId, |
| turn_id: String, |
| ) -> CloudBackendFuture<'_, Vec<TurnAttempt>>; |
| |
| |
| |
| fn apply_task_preflight( |
| &self, |
| id: TaskId, |
| diff_override: Option<String>, |
| ) -> CloudBackendFuture<'_, ApplyOutcome>; |
| fn apply_task( |
| &self, |
| id: TaskId, |
| diff_override: Option<String>, |
| ) -> CloudBackendFuture<'_, ApplyOutcome>; |
| fn create_task<'a>( |
| &'a self, |
| env_id: &'a str, |
| prompt: &'a str, |
| git_ref: &'a str, |
| qa_mode: bool, |
| best_of_n: usize, |
| ) -> CloudBackendFuture<'a, CreatedTask>; |
| } |
|
|