lellm_graph/node/compiled_subgraph.rs
1//! CompiledSubgraph — 编译后的 Subgraph 描述符。
2//!
3//! # 设计理念
4//!
5//! ```text
6//! Builder 阶段:
7//! SubgraphSpec<Outer, Inner, M, Lens> (强类型)
8//!
9//! 编译阶段:
10//! CompiledSubgraph<Outer> (类型擦除 Inner/Lens/M)
11//!
12//! Engine 执行:
13//! match node.kind {
14//! NodeKind::Subgraph(spec) => self.execute_subgraph(spec).await,
15//! }
16//! ```
17//!
18//! # 类型擦除
19//!
20//! SubgraphSpec 有 4 个泛型参数,NodeKind 只有 2 个。
21//! CompiledSubgraph 通过 `StateProjector` trait 擦除 Inner/Lens/M,
22//! 只保留 Outer(外层 State 类型)。
23//!
24//! # 与 SubgraphSpec 的区别
25//!
26//! - SubgraphSpec:Builder 阶段,强类型,包含 Graph + Lens
27//! - CompiledSubgraph:编译后,类型擦除,可存入 NodeKind
28
29use std::future::Future;
30use std::pin::Pin;
31use std::sync::Arc;
32
33use crate::error::GraphError;
34use crate::state::workflow_state::WorkflowState;
35use crate::stream_emitter::StreamSink;
36use tokio_util::sync::CancellationToken;
37
38// ─── StateProjector ────────────────────────────────────────────
39
40/// 状态投影器 — 类型擦除的 Outer → Inner 投影 + 执行。
41///
42/// 这是 Subgraph 执行的核心 trait。它擦除了 Inner、Lens、Merge 类型,
43/// 只暴露 Outer State 类型。
44///
45/// # 设计原则
46///
47/// - 最小接口:只有 `execute()` + 元数据方法
48/// - 类型擦除:Inner/Lens/M 全部隐藏在实现内部
49/// - 可 introspection:提供 `graph_name()` 和 `node_count()`
50pub trait StateProjector<S: WorkflowState>: Send + Sync {
51 /// 执行 Subgraph — 投影状态 + 递归执行内层 Graph。
52 fn execute<'a>(
53 &'a self,
54 outer: &'a mut S,
55 stream: Option<Arc<dyn StreamSink>>,
56 cancel: CancellationToken,
57 ) -> Pin<Box<dyn Future<Output = Result<(), GraphError>> + Send + 'a>>;
58
59 /// 内层 Graph 的名称。
60 fn graph_name(&self) -> &str;
61
62 /// 内层 Graph 的节点数(用于评估是否值得内联)。
63 fn node_count(&self) -> usize;
64}
65
66// ─── CompiledSubgraph ──────────────────────────────────────────
67
68/// 编译后的 Subgraph 描述符 — 可存入 NodeKind。
69///
70/// # 类型参数
71///
72/// - `S` — 外层 State 类型(与 NodeKind 一致)
73///
74/// # 内容
75///
76/// - `projector` — 类型擦除的执行器(包含 Graph + Lens + Merge)
77/// - `max_steps` — 最大执行步数
78///
79/// # 使用方式
80///
81/// ```text
82/// NodeKind::Subgraph(CompiledSubgraph {
83/// projector: Arc::new(spec), // SubgraphSpec implements StateProjector
84/// max_steps: 1000,
85/// })
86/// ```
87#[derive(Clone)]
88pub struct CompiledSubgraph<S: WorkflowState> {
89 /// 类型擦除的执行器
90 pub projector: Arc<dyn StateProjector<S>>,
91 /// 最大执行步数
92 pub max_steps: usize,
93}
94
95impl<S: WorkflowState> CompiledSubgraph<S> {
96 /// 创建新的 CompiledSubgraph。
97 pub fn new(projector: Arc<dyn StateProjector<S>>, max_steps: usize) -> Self {
98 Self {
99 projector,
100 max_steps,
101 }
102 }
103
104 /// 执行 Subgraph。
105 pub async fn execute(
106 &self,
107 outer: &mut S,
108 stream: Option<Arc<dyn StreamSink>>,
109 cancel: CancellationToken,
110 ) -> Result<(), GraphError> {
111 self.projector.execute(outer, stream, cancel).await
112 }
113
114 /// 内层 Graph 的名称。
115 pub fn graph_name(&self) -> &str {
116 self.projector.graph_name()
117 }
118
119 /// 内层 Graph 的节点数。
120 pub fn node_count(&self) -> usize {
121 self.projector.node_count()
122 }
123}
124
125impl<S: WorkflowState> std::fmt::Debug for CompiledSubgraph<S> {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 f.debug_struct("CompiledSubgraph")
128 .field("graph_name", &self.projector.graph_name())
129 .field("node_count", &self.projector.node_count())
130 .field("max_steps", &self.max_steps)
131 .finish()
132 }
133}