use super::super::edge::GraphEdge;
use super::super::node::GraphNode;
use super::super::state::{StateSchema, StateUpdate};
use async_trait::async_trait;
use serde_json::Value as JsonValue;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Debug)]
pub struct GraphInvocation<S: StateSchema> {
pub final_state: S,
pub steps: Vec<ExecutionStep>,
pub recursion_count: usize,
}
impl<S: StateSchema> GraphInvocation<S> {
pub fn state(&self) -> &S {
&self.final_state
}
pub fn steps(&self) -> &[ExecutionStep] {
&self.steps
}
}
#[derive(Debug, Clone)]
pub enum ExecutionStep {
Node {
name: String,
metadata: HashMap<String, JsonValue>,
},
Checkpoint {
id: String,
next_node: String,
},
ParallelNode {
branch: String,
metadata: HashMap<String, JsonValue>,
},
}
impl ExecutionStep {
pub fn node(name: String, metadata: HashMap<String, JsonValue>) -> Self {
Self::Node { name, metadata }
}
pub fn checkpoint(id: String, next_node: String) -> Self {
Self::Checkpoint { id, next_node }
}
pub fn parallel_node(branch: String, metadata: HashMap<String, JsonValue>) -> Self {
Self::ParallelNode { branch, metadata }
}
}
#[derive(Debug, Clone)]
pub struct ParallelBranch<S: StateSchema> {
pub name: String,
pub final_state: S,
pub steps: Vec<ExecutionStep>,
}
#[derive(Debug)]
pub struct ParallelInvocation<S: StateSchema> {
pub final_state: S,
pub steps: Vec<ExecutionStep>,
pub recursion_count: usize,
pub parallel_branches: Vec<ParallelBranch<S>>,
}
impl<S: StateSchema> ParallelInvocation<S> {
pub fn state(&self) -> &S {
&self.final_state
}
pub fn branches(&self) -> &[ParallelBranch<S>] {
&self.parallel_branches
}
}
#[derive(Debug, Clone)]
pub enum StreamEvent<S: StateSchema> {
Start(S),
EnterNode(String, S),
NodeComplete(String, StateUpdate<S>),
StateUpdate(S),
End(S),
}
impl<S: StateSchema> StreamEvent<S> {
pub fn start(state: S) -> Self {
Self::Start(state)
}
pub fn enter_node(name: String, state: S) -> Self {
Self::EnterNode(name, state)
}
pub fn node_complete(name: String, update: StateUpdate<S>) -> Self {
Self::NodeComplete(name, update)
}
pub fn state_update(state: S) -> Self {
Self::StateUpdate(state)
}
pub fn end(state: S) -> Self {
Self::End(state)
}
}
#[derive(Debug, Clone)]
pub struct GraphExecution<S: StateSchema> {
pub state: S,
pub current_node: String,
pub steps: Vec<ExecutionStep>,
pub recursion_count: usize,
pub interrupted_at: String,
}
impl<S: StateSchema> GraphExecution<S> {
pub fn new(state: S, current_node: String, interrupted_at: String) -> Self {
Self {
state,
current_node,
steps: Vec::new(),
recursion_count: 0,
interrupted_at,
}
}
pub fn state(&self) -> &S {
&self.state
}
pub fn interrupted_at(&self) -> &str {
&self.interrupted_at
}
}
#[derive(Debug, Clone)]
pub struct DynamicTask {
pub id: String,
pub description: String,
}
pub struct DynamicInjection<S: StateSchema> {
pub nodes: Vec<(String, Arc<dyn GraphNode<S>>)>,
pub edges: Vec<GraphEdge>,
}
#[async_trait]
pub trait DynamicPlanner<S: StateSchema>: Send + Sync {
async fn plan(
&self,
tasks: &[DynamicTask],
current_state: &S,
) -> Result<DynamicInjection<S>, String>;
}