优化: miniapp渲染(图片/checkbox/代码高亮) + MCP规则共享下沉 + 文档重写 + 节点风格对齐
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
//! 任务创建参数校验(共享层)
|
||||
//!
|
||||
//! GUI AI 工具(ai/tools/task.rs)与 MCP 工具(crates/df-mcp/src/tools.rs)曾各自内联
|
||||
//! 一套 create_task 校验(queue 白名单 / parent_id 嵌套铁律 / content_json 合法性),
|
||||
//! 演进易漂移。抽到本模块后两套工具同源复用,一处修改全局生效。
|
||||
|
||||
use crate::crud::task_repo::TaskRepo;
|
||||
|
||||
/// queue 合法值白名单(queue 是独立管理维度,与 status 执行维度正交)
|
||||
pub const TASK_QUEUE_VALUES: &[&str] = &["backlog", "todo", "decision", "active", "done"];
|
||||
|
||||
/// 默认优先级(medium)— 新任务默认中优先级,与 IPC create_task 一致
|
||||
pub const DEFAULT_TASK_PRIORITY: i32 = 2;
|
||||
|
||||
/// 校验并归一化 create_task 的 queue:空串/缺省 → "todo";
|
||||
/// 白名单校验 + create 一致性(新建仅 backlog/todo/decision,active/done 须经 move_task_queue 流转)。
|
||||
pub fn normalize_queue_for_create(queue: Option<&str>) -> Result<String, String> {
|
||||
match queue {
|
||||
None | Some("") => Ok("todo".to_string()),
|
||||
Some(q) => {
|
||||
let q = q.trim();
|
||||
if !TASK_QUEUE_VALUES.contains(&q) {
|
||||
return Err(format!("非法 queue 值 {:?},合法值: {:?}", q, TASK_QUEUE_VALUES));
|
||||
}
|
||||
match q {
|
||||
"backlog" | "todo" | "decision" => Ok(q.to_string()),
|
||||
other => Err(format!(
|
||||
"新建任务 queue 不可直接落 {:?}(须经 move_task_queue 流转),当前仅允许 backlog/todo/decision",
|
||||
other
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 校验 content_json(非空时须是合法 JSON),返回规范化值(None=未传)。
|
||||
pub fn validate_content_json(content: Option<&str>) -> Result<Option<String>, String> {
|
||||
match content {
|
||||
Some(c) if !c.trim().is_empty() => {
|
||||
serde_json::from_str::<serde_json::Value>(c)
|
||||
.map_err(|e| format!("content_json 不是合法 JSON: {e}"))?;
|
||||
Ok(Some(c.to_string()))
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// 校验 parent_id 1 级嵌套铁律:父任务存在 + 父任务自身不是子任务(防孙任务)。
|
||||
/// 返回归一化 parent_id(空串/缺省 → None)。
|
||||
pub async fn validate_parent_id(
|
||||
repo: &TaskRepo,
|
||||
parent_id: Option<&str>,
|
||||
) -> Result<Option<String>, String> {
|
||||
let pid = parent_id
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty());
|
||||
if let Some(pid) = &pid {
|
||||
let parent = repo
|
||||
.get_by_id(pid)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.ok_or_else(|| format!("父任务 {pid} 不存在,无法创建子任务"))?;
|
||||
if parent.parent_id.is_some() {
|
||||
return Err(format!(
|
||||
"违反 1 级嵌套铁律:父任务 {pid} 自身是子任务(parent_id={:?}),不允许在其下创建孙任务",
|
||||
parent.parent_id
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(pid)
|
||||
}
|
||||
|
||||
/// 校验并归一化 create_task 的 priority:缺省 → DEFAULT_TASK_PRIORITY;越界值拒绝(值域 0..=3)。
|
||||
pub fn normalize_priority(priority: Option<i64>) -> Result<i32, String> {
|
||||
match priority {
|
||||
None => Ok(DEFAULT_TASK_PRIORITY),
|
||||
Some(p) if (0..=3).contains(&p) => Ok(p as i32),
|
||||
Some(p) => Err(format!(
|
||||
"非法 priority 值 {p},合法值: 整数 0..=3(0=critical, 1=high, 2=medium, 3=low)"
|
||||
)),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user