新增: 初始化 DevFlow 项目仓库

Tauri 2 + Vue 3 + Vite 6 桌面应用,Rust workspace 含 13 个 crate
(df-ai / df-storage / df-workflow / df-core / df-execute 等)。
核心能力:AI 聊天 agentic 循环(工具调用+人工审批)、工作流引擎、
任务/想法/项目/阶段管理、可追溯性,及配套前端组件。
This commit is contained in:
2026-06-12 01:31:05 +08:00
commit 98393b4908
178 changed files with 27859 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
//! DAG有向无环图定义与拓扑排序
use std::collections::{HashMap, HashSet, VecDeque};
use df_core::error::Result;
use df_core::types::NodeId;
use crate::node::Node;
/// 图的边:从 source 到 target
#[derive(Debug, Clone)]
pub struct Edge {
pub source: NodeId,
pub target: NodeId,
/// 边的条件表达式(可选)
pub condition: Option<String>,
}
/// DAG 结构
pub struct Dag {
/// 节点集合
pub nodes: HashMap<NodeId, Box<dyn Node>>,
/// 边集合
pub edges: Vec<Edge>,
}
impl Dag {
/// 创建空 DAG
pub fn new() -> Self {
Self {
nodes: HashMap::new(),
edges: Vec::new(),
}
}
/// 添加节点
pub fn add_node(&mut self, id: NodeId, node: Box<dyn Node>) {
self.nodes.insert(id, node);
}
/// 添加边
pub fn add_edge(&mut self, source: NodeId, target: NodeId) {
self.edges.push(Edge {
source,
target,
condition: None,
});
}
/// 添加带条件的边
pub fn add_edge_with_condition(
&mut self,
source: NodeId,
target: NodeId,
condition: String,
) {
self.edges.push(Edge {
source,
target,
condition: Some(condition),
});
}
/// 获取指定节点的所有上游节点 ID
pub fn predecessors(&self, node_id: &NodeId) -> Vec<NodeId> {
self.edges
.iter()
.filter(|e| &e.target == node_id)
.map(|e| e.source.clone())
.collect()
}
/// 获取指定节点的所有下游节点 ID
pub fn successors(&self, node_id: &NodeId) -> Vec<NodeId> {
self.edges
.iter()
.filter(|e| &e.source == node_id)
.map(|e| e.target.clone())
.collect()
}
/// 拓扑排序 — 返回按执行顺序排列的节点 ID 层级
///
/// 返回 Vec<Vec<NodeId>>,每层内的节点可以并行执行
pub fn topological_layers(&self) -> Result<Vec<Vec<NodeId>>> {
let node_ids: HashSet<NodeId> = self.nodes.keys().cloned().collect();
let mut in_degree: HashMap<NodeId, usize> = HashMap::new();
// 初始化入度
for id in &node_ids {
in_degree.insert(id.clone(), 0);
}
for edge in &self.edges {
if node_ids.contains(&edge.source) && node_ids.contains(&edge.target) {
*in_degree.entry(edge.target.clone()).or_insert(0) += 1;
}
}
// BFS 分层
let mut layers = Vec::new();
let mut queue: VecDeque<NodeId> = in_degree
.iter()
.filter(|(_, &deg)| deg == 0)
.map(|(id, _)| id.clone())
.collect();
let mut processed = 0usize;
while !queue.is_empty() {
let mut layer: Vec<NodeId> = Vec::new();
let layer_size = queue.len();
for _ in 0..layer_size {
if let Some(id) = queue.pop_front() {
layer.push(id.clone());
for succ in self.successors(&id) {
let deg = in_degree.get_mut(&succ).unwrap();
*deg -= 1;
if *deg == 0 {
queue.push_back(succ);
}
}
processed += 1;
}
}
layers.push(layer);
}
if processed != node_ids.len() {
return Err(df_core::error::Error::Workflow(
"DAG 中存在环,无法进行拓扑排序".to_string(),
));
}
Ok(layers)
}
}
impl Default for Dag {
fn default() -> Self {
Self::new()
}
}