Files
DevFlow/crates/df-workflow/src/conditions.rs
绝尘 cf017f81e2 新增: Phase2 阶段收尾(Sprint 1-20)
重构:删 5 零引用 crate(df-evolve/plugin/stages/task/traceability)+ 清死模块、ai.rs 拆 11 子 module、ai.ts 拆 6 composable、i18n 拆目录
功能:知识库全栈(df-project/scan + CRUD + 时间线 + 前端)、Settings 拆分、appSettings KV 迁移、模型池、LLM 并发 Semaphore
修复:审批持久化根治、ConditionEngine 默认拒绝、NodeRegistry unimplemented 清除、promote 补偿删除、工具结果截断 50KB、路径校验防 symlink 逃逸
文档:B-03 人工审批设计、决策记录三分档、规格契约自检、经验记录、todo 看板、PROGRESS 更新

详见 PROGRESS.md。src-tauri/儿童每日打卡应用/ 与本项目无关,已排除。
2026-06-14 14:08:20 +08:00

98 lines
3.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 条件表达式引擎 — 用于 DAG 边上的条件判断
//!
//! TODO: 实现完整的条件表达式解析与求值
use serde_json::Value;
/// 条件表达式求值器
pub struct ConditionEngine;
impl ConditionEngine {
/// 求值条件表达式
///
/// 当前仅支持 "true"/"false" 字面量。未识别的表达式 **默认 false**(保守拒绝),
/// 而非默认 true——条件分支写错或引擎未实现时不应该静默放行。
/// TODO: 实现完整的表达式解析JSON Path / 数值比较 / contains / 逻辑组合)。
pub fn evaluate(expr: &str, _context: &Value) -> anyhow::Result<bool> {
let trimmed = expr.trim();
if trimmed == "true" {
return Ok(true);
}
if trimmed == "false" {
return Ok(false);
}
// TODO: 实现如下语法:
// - "$.status == 'completed'" — JSON Path 比较
// - "$.count > 10" — 数值比较
// - "$.tags contains 'ai'" — 包含检查
// - "and/or/not" — 逻辑组合
tracing::warn!("条件表达式引擎尚未完整实现,表达式未识别默认 false: {}", expr);
Ok(false)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
fn ctx() -> Value {
// 当前实现未使用 context但保持传入以对齐签名
json!({})
}
#[test]
fn test_true_literal_returns_true() {
assert_eq!(ConditionEngine::evaluate("true", &ctx()).unwrap(), true);
}
#[test]
fn test_false_literal_returns_false() {
assert_eq!(ConditionEngine::evaluate("false", &ctx()).unwrap(), false);
}
#[test]
fn test_unsupported_expression_defaults_to_false() {
// 尚未实现的语法:表达式非 true/false 字面量时默认 false(保守拒绝,不静默放行)
assert_eq!(
ConditionEngine::evaluate("$.status == 'completed'", &ctx()).unwrap(),
false
);
}
#[test]
fn test_whitespace_is_trimmed() {
// trimmed() 去除首尾空白后再与字面量比较
assert_eq!(
ConditionEngine::evaluate(" true ", &ctx()).unwrap(),
true
);
assert_eq!(
ConditionEngine::evaluate("\tfalse\n", &ctx()).unwrap(),
false
);
}
#[test]
fn test_empty_string_defaults_to_false() {
assert_eq!(ConditionEngine::evaluate("", &ctx()).unwrap(), false);
assert_eq!(ConditionEngine::evaluate(" ", &ctx()).unwrap(), false);
}
#[test]
fn test_case_sensitive_not_matched() {
// 字面量比较区分大小写:True/False 既非 "true" 也非 "false",默认 false
assert_eq!(ConditionEngine::evaluate("True", &ctx()).unwrap(), false);
assert_eq!(ConditionEngine::evaluate("FALSE", &ctx()).unwrap(), false);
}
#[test]
fn test_arbitrary_string_defaults_to_false() {
assert_eq!(ConditionEngine::evaluate("yes", &ctx()).unwrap(), false);
assert_eq!(ConditionEngine::evaluate("1", &ctx()).unwrap(), false);
assert_eq!(ConditionEngine::evaluate("completed", &ctx()).unwrap(), false);
}
}