use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
use serde::{Deserialize, Serialize};
use crate::error::Result;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentTask {
pub task_id: String,
pub input: String,
pub run_id: Option<String>,
pub metadata: HashMap<String, serde_json::Value>,
}
impl AgentTask {
pub fn new(input: impl Into<String>) -> Self {
Self {
task_id: Self::generate_id(),
input: input.into(),
run_id: None,
metadata: HashMap::new(),
}
}
pub fn with_run_id(mut self, run_id: impl Into<String>) -> Self {
self.run_id = Some(run_id.into());
self
}
pub fn with_metadata(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
self.metadata.insert(key.into(), value);
self
}
fn generate_id() -> String {
use std::time::{SystemTime, UNIX_EPOCH};
let ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_nanos();
format!("task-{ts:x}")
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TaskResult {
pub task_id: String,
pub output: String,
pub iterations: usize,
pub cost: f64,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskStatus {
Pending,
Running,
Completed(TaskResult),
Failed(String),
}
pub trait TaskBroker: Send + Sync {
fn submit(&self, task: AgentTask) -> impl Future<Output = Result<String>> + Send;
fn status(&self, task_id: &str) -> impl Future<Output = Result<TaskStatus>> + Send;
fn receive(&self) -> impl Future<Output = Result<Option<AgentTask>>> + Send;
fn complete(
&self,
task_id: &str,
result: TaskResult,
) -> impl Future<Output = Result<()>> + Send;
fn fail(&self, task_id: &str, error: String) -> impl Future<Output = Result<()>> + Send;
}
pub trait ErasedTaskBroker: Send + Sync {
fn submit_erased<'a>(
&'a self,
task: AgentTask,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'a>>;
fn status_erased<'a>(
&'a self,
task_id: &'a str,
) -> Pin<Box<dyn Future<Output = Result<TaskStatus>> + Send + 'a>>;
fn receive_erased(
&self,
) -> Pin<Box<dyn Future<Output = Result<Option<AgentTask>>> + Send + '_>>;
fn complete_erased<'a>(
&'a self,
task_id: &'a str,
result: TaskResult,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
fn fail_erased<'a>(
&'a self,
task_id: &'a str,
error: String,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
}
impl<T: TaskBroker> ErasedTaskBroker for T {
fn submit_erased<'a>(
&'a self,
task: AgentTask,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'a>> {
Box::pin(self.submit(task))
}
fn status_erased<'a>(
&'a self,
task_id: &'a str,
) -> Pin<Box<dyn Future<Output = Result<TaskStatus>> + Send + 'a>> {
Box::pin(self.status(task_id))
}
fn receive_erased(
&self,
) -> Pin<Box<dyn Future<Output = Result<Option<AgentTask>>> + Send + '_>> {
Box::pin(self.receive())
}
fn complete_erased<'a>(
&'a self,
task_id: &'a str,
result: TaskResult,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.complete(task_id, result))
}
fn fail_erased<'a>(
&'a self,
task_id: &'a str,
error: String,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.fail(task_id, error))
}
}