优化: miniapp渲染(图片/checkbox/代码高亮) + MCP规则共享下沉 + 文档重写 + 节点风格对齐

This commit is contained in:
lxy
2026-08-08 21:39:30 +08:00
parent 9eb2995a74
commit e7228231d1
11 changed files with 587 additions and 167 deletions
+3
View File
@@ -6,6 +6,7 @@
//! - [`mod@settings`]:SettingsRepo + 列白名单(allowed_columns_for/validate_column_name/is_allowed_column)
//! - [`mod@project_repo`]:ProjectRepo/BranchRepo/ReleaseRepo/WorkflowRepo/NodeExecutionRepo
//! - [`mod@task_repo`]:TaskRepo(含 advance_status_atomic 状态机收口)
//! - [`mod@task_validation`]:任务创建参数校验(queue 白名单/parent_id 嵌套铁律/content_json),GUI 与 MCP 工具共享
//! - [`mod@task_link_repo`]:TaskLinkRepo(任务横向关联 task_links,V29,知识图谱 Phase 1)
//! - [`mod@project_event_repo`]:ProjectEventRepo(统一事件流 project_events,V30,知识图谱 Phase 2)
//! - [`mod@project_service_repo`]:ProjectServiceRepo(基础设施配置 project_services,V31,知识图谱 Phase 3)
@@ -31,6 +32,7 @@ mod project_service_repo;
mod settings;
mod task_link_repo;
mod task_repo;
mod task_validation;
pub use conversation_repo::*;
pub use idea_eval_repo::*;
@@ -43,6 +45,7 @@ pub use project_service_repo::*;
pub use settings::*;
pub use task_link_repo::*;
pub use task_repo::*;
pub use task_validation::*;
pub use module_dependency_repo::*;
pub use plan_repo::*;
@@ -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)"
)),
}
}