use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::kernel::identity::RunId;
use crate::kernel::KernelError;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Action {
CallTool {
tool: String,
input: Value,
},
CallLLM {
provider: String,
input: Value,
},
Sleep {
millis: u64,
},
WaitSignal {
name: String,
},
}
#[derive(Clone, Debug)]
pub enum ActionResult {
Success(Value),
Failure(String),
}
#[derive(Clone, Debug)]
pub enum ActionErrorKind {
Transient,
Permanent,
RateLimited,
}
#[derive(Clone, Debug)]
pub struct ActionError {
pub kind: ActionErrorKind,
pub message: String,
pub retry_after_ms: Option<u64>,
}
impl ActionError {
pub fn transient(message: impl Into<String>) -> Self {
Self {
kind: ActionErrorKind::Transient,
message: message.into(),
retry_after_ms: None,
}
}
pub fn permanent(message: impl Into<String>) -> Self {
Self {
kind: ActionErrorKind::Permanent,
message: message.into(),
retry_after_ms: None,
}
}
pub fn rate_limited(message: impl Into<String>, retry_after_ms: u64) -> Self {
Self {
kind: ActionErrorKind::RateLimited,
message: message.into(),
retry_after_ms: Some(retry_after_ms),
}
}
pub fn from_kernel_error(e: &KernelError) -> Self {
if let KernelError::Executor(ae) = e {
ae.clone()
} else {
Self::permanent(e.to_string())
}
}
}
impl std::fmt::Display for ActionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
pub trait ActionExecutor: Send + Sync {
fn execute(&self, run_id: &RunId, action: &Action) -> Result<ActionResult, KernelError>;
}