use async_trait::async_trait;
use std::fmt;
use super::response_store::StoreError;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StepKind {
ModelCall,
ToolCall,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StepState {
Pending,
Processing,
Completed,
Failed,
Canceled,
}
impl StepState {
pub fn is_terminal(&self) -> bool {
matches!(self, Self::Completed | Self::Failed | Self::Canceled)
}
}
#[derive(Debug, Clone)]
pub struct StepDescriptor {
pub kind: StepKind,
pub request_payload: serde_json::Value,
}
#[derive(Debug, Clone)]
pub enum NextAction {
AppendSteps(Vec<StepDescriptor>),
Complete(serde_json::Value),
Fail(serde_json::Value),
}
#[derive(Debug, Clone)]
pub struct RecordedStep {
pub id: String,
pub sequence: i64,
}
#[derive(Debug, Clone)]
pub struct ChainStep {
pub id: String,
pub kind: StepKind,
pub state: StepState,
pub sequence: i64,
pub prev_step_id: Option<String>,
pub parent_step_id: Option<String>,
pub response_payload: Option<serde_json::Value>,
pub error: Option<serde_json::Value>,
}
#[async_trait]
pub trait MultiStepStore: Send + Sync {
async fn next_action_for(
&self,
request_id: &str,
scope_parent: Option<&str>,
) -> Result<NextAction, StoreError>;
async fn record_step(
&self,
request_id: &str,
scope_parent: Option<&str>,
prev_step: Option<&str>,
descriptor: &StepDescriptor,
) -> Result<RecordedStep, StoreError>;
async fn mark_step_processing(&self, step_id: &str) -> Result<(), StoreError>;
async fn complete_step(
&self,
step_id: &str,
payload: &serde_json::Value,
) -> Result<(), StoreError>;
async fn fail_step(&self, step_id: &str, error: &serde_json::Value) -> Result<(), StoreError>;
async fn list_chain(
&self,
request_id: &str,
scope_parent: Option<&str>,
) -> Result<Vec<ChainStep>, StoreError>;
async fn assemble_response(&self, request_id: &str) -> Result<serde_json::Value, StoreError>;
}
#[derive(Debug, Clone)]
pub enum ExecutorError {
NotFound(String),
ExecutionError(String),
}
impl fmt::Display for ExecutorError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotFound(name) => write!(f, "executor target not found: {}", name),
Self::ExecutionError(msg) => write!(f, "executor error: {}", msg),
}
}
}
impl std::error::Error for ExecutorError {}