use serde::{Deserialize, Serialize};
use serde_json::Value;
use super::Meta;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[expect(clippy::exhaustive_enums, reason = "intentionally exhaustive")]
pub enum TaskStatus {
#[default]
Working,
InputRequired,
Completed,
Failed,
Cancelled,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[non_exhaustive]
pub struct Task {
pub task_id: String,
pub status: TaskStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub status_message: Option<String>,
pub created_at: String,
pub last_updated_at: String,
pub ttl: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub poll_interval: Option<u64>,
}
impl Task {
pub fn new(
task_id: String,
status: TaskStatus,
created_at: String,
last_updated_at: String,
) -> Self {
Self {
task_id,
status,
status_message: None,
created_at,
last_updated_at,
ttl: None,
poll_interval: None,
}
}
pub fn with_status_message(mut self, status_message: impl Into<String>) -> Self {
self.status_message = Some(status_message.into());
self
}
pub fn with_ttl(mut self, ttl: u64) -> Self {
self.ttl = Some(ttl);
self
}
pub fn with_poll_interval(mut self, poll_interval: u64) -> Self {
self.poll_interval = Some(poll_interval);
self
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[non_exhaustive]
pub struct CreateTaskResult {
pub task: Task,
}
impl CreateTaskResult {
pub fn new(task: Task) -> Self {
Self { task }
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
pub struct GetTaskResult {
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
#[serde(flatten)]
pub task: Task,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[non_exhaustive]
pub struct GetTaskPayloadResult(pub Value);
impl GetTaskPayloadResult {
pub fn new(value: Value) -> Self {
Self(value)
}
}
impl<'de> serde::Deserialize<'de> for GetTaskPayloadResult {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
serde::de::IgnoredAny::deserialize(deserializer)?;
Err(serde::de::Error::custom(
"GetTaskPayloadResult cannot be deserialized directly; \
use CustomResult as the catch-all",
))
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
pub struct CancelTaskResult {
#[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
pub meta: Option<Meta>,
#[serde(flatten)]
pub task: Task,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
pub struct TaskList {
pub tasks: Vec<Task>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_cursor: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub total: Option<u64>,
}
impl TaskList {
pub fn new(tasks: Vec<Task>) -> Self {
Self {
tasks,
next_cursor: None,
total: None,
}
}
}