Skip to main content

lc_langgraph/compiled/
types.rs

1// crates/lc-langgraph/src/compiled/types.rs
2//! Public types for graph execution results and streaming events
3
4use crate::edge::GraphEdge;
5use crate::node::GraphNode;
6use crate::state::{StateSchema, StateUpdate};
7use async_trait::async_trait;
8use serde_json::Value as JsonValue;
9use std::collections::HashMap;
10use std::sync::Arc;
11
12/// GraphInvocation - Result of graph execution
13#[derive(Debug)]
14pub struct GraphInvocation<S: StateSchema> {
15    pub final_state: S,
16    pub steps: Vec<ExecutionStep>,
17    pub recursion_count: usize,
18}
19
20impl<S: StateSchema> GraphInvocation<S> {
21    pub fn state(&self) -> &S {
22        &self.final_state
23    }
24
25    pub fn steps(&self) -> &[ExecutionStep] {
26        &self.steps
27    }
28}
29
30/// ExecutionStep - Single step in execution history
31#[derive(Debug, Clone)]
32pub enum ExecutionStep {
33    Node {
34        name: String,
35        metadata: HashMap<String, JsonValue>,
36    },
37    Checkpoint {
38        id: String,
39        next_node: String,
40    },
41    ParallelNode {
42        branch: String,
43        metadata: HashMap<String, JsonValue>,
44    },
45}
46
47impl ExecutionStep {
48    pub fn node(name: String, metadata: HashMap<String, JsonValue>) -> Self {
49        Self::Node { name, metadata }
50    }
51
52    pub fn checkpoint(id: String, next_node: String) -> Self {
53        Self::Checkpoint { id, next_node }
54    }
55
56    pub fn parallel_node(branch: String, metadata: HashMap<String, JsonValue>) -> Self {
57        Self::ParallelNode { branch, metadata }
58    }
59}
60
61/// ParallelBranch - Result of a parallel execution branch
62#[derive(Debug, Clone)]
63pub struct ParallelBranch<S: StateSchema> {
64    pub name: String,
65    pub final_state: S,
66    pub steps: Vec<ExecutionStep>,
67}
68
69/// ParallelInvocation - Result of graph execution with parallel branches
70#[derive(Debug)]
71pub struct ParallelInvocation<S: StateSchema> {
72    pub final_state: S,
73    pub steps: Vec<ExecutionStep>,
74    pub recursion_count: usize,
75    pub parallel_branches: Vec<ParallelBranch<S>>,
76}
77
78impl<S: StateSchema> ParallelInvocation<S> {
79    pub fn state(&self) -> &S {
80        &self.final_state
81    }
82
83    pub fn branches(&self) -> &[ParallelBranch<S>] {
84        &self.parallel_branches
85    }
86}
87
88/// StreamEvent - Event for streaming execution
89#[derive(Debug, Clone)]
90pub enum StreamEvent<S: StateSchema> {
91    Start(S),
92    EnterNode(String, S),
93    NodeComplete(String, StateUpdate<S>),
94    StateUpdate(S),
95    End(S),
96}
97
98impl<S: StateSchema> StreamEvent<S> {
99    pub fn start(state: S) -> Self {
100        Self::Start(state)
101    }
102
103    pub fn enter_node(name: String, state: S) -> Self {
104        Self::EnterNode(name, state)
105    }
106
107    pub fn node_complete(name: String, update: StateUpdate<S>) -> Self {
108        Self::NodeComplete(name, update)
109    }
110
111    pub fn state_update(state: S) -> Self {
112        Self::StateUpdate(state)
113    }
114
115    pub fn end(state: S) -> Self {
116        Self::End(state)
117    }
118}
119
120/// GraphExecution - State for interrupted execution that can be resumed
121#[derive(Debug, Clone)]
122pub struct GraphExecution<S: StateSchema> {
123    pub state: S,
124    pub current_node: String,
125    pub steps: Vec<ExecutionStep>,
126    pub recursion_count: usize,
127    pub interrupted_at: String,
128}
129
130impl<S: StateSchema> GraphExecution<S> {
131    pub fn new(state: S, current_node: String, interrupted_at: String) -> Self {
132        Self {
133            state,
134            current_node,
135            steps: Vec::new(),
136            recursion_count: 0,
137            interrupted_at,
138        }
139    }
140
141    pub fn state(&self) -> &S {
142        &self.state
143    }
144
145    pub fn interrupted_at(&self) -> &str {
146        &self.interrupted_at
147    }
148}
149
150// ── Dynamic extension types ──
151
152/// A task submitted externally for dynamic planning mid-execution.
153#[derive(Debug, Clone)]
154pub struct DynamicTask {
155    pub id: String,
156    pub description: String,
157}
158
159/// Result of dynamic planning: nodes and edges to inject into a running graph.
160pub struct DynamicInjection<S: StateSchema> {
161    pub nodes: Vec<(String, Arc<dyn GraphNode<S>>)>,
162    pub edges: Vec<GraphEdge>,
163}
164
165/// Planner trait for converting external tasks into graph nodes/edges at runtime.
166#[async_trait]
167pub trait DynamicPlanner<S: StateSchema>: Send + Sync {
168    /// Given pending tasks and current state, produce nodes/edges to inject.
169    async fn plan(
170        &self,
171        tasks: &[DynamicTask],
172        current_state: &S,
173    ) -> Result<DynamicInjection<S>, String>;
174}