feat(mcp): unregister_project agent 按钮——登记卫生工具对补全
scan_unregistered_projects 发现漏网,unregister_project 清理死账。 薄包装调 delete_project 本体(UI 删除按钮同源),delete_local 硬编码 false——MCP 侧永不暴露删本地文件能力(安全边界)。 工具描述内置约束:删除不可逆,调用前须向用户列清单确认。 Rules-Applied: R12,R13
This commit is contained in:
parent
94d8be6eb6
commit
f03e4178fc
@ -246,6 +246,17 @@ pub fn tools_list_result() -> Value {
|
||||
"description": "扫描已登记项目的父目录,找出存在于文件系统但尚未在炼境注册的项目目录。返回每个未注册目录的路径、是否有 .git、技术栈特征文件(package.json / Cargo.toml / go.mod)、是否有 AGENTS.md。用于日常发现漏网项目并决定是否接入炼境。",
|
||||
"inputSchema": { "type": "object", "properties": {}, "required": [] }
|
||||
},
|
||||
{
|
||||
"name": "unregister_project",
|
||||
"description": "从炼境删除一条项目登记(等价 UI 删除项目按钮的 agent 投影):清理产品组 MCP 配置、关联表、workspace 与孤儿 profile。绝不删除本地文件(该能力不对 agent 开放)。适用:scan_unregistered_projects 的反向操作——清理目录已消失或已无 .git 的死登记。删除不可逆,调用前先向用户列出目标清单确认。",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"project_id": { "type": "string", "description": "要删除登记的项目 workspace ID" }
|
||||
},
|
||||
"required": ["project_id"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ingest_git_history",
|
||||
"description": "全量导入 git 历史到飞轮(等价 UI「全量导入」按钮的 agent 投影):解析最近 500 条 commit 的 conventional 指标、Rules-Applied trailer 与触碰文件,UPSERT 幂等(存量行自动回填 trailer)。不传 project_id 时对所有已登记 Windows 路径项目执行。适用:trailer 存量回填、新项目接入后初始化飞轮数据。",
|
||||
@ -486,6 +497,16 @@ pub async fn tools_call(group_id: &str, params: Option<&Value>) -> Value {
|
||||
}
|
||||
"list_all_projects" => list_all_projects(),
|
||||
"scan_unregistered_projects" => scan_unregistered_projects(),
|
||||
"unregister_project" => {
|
||||
let pid = args.get("project_id").and_then(|v| v.as_str()).unwrap_or("");
|
||||
if pid.is_empty() {
|
||||
Err("project_id 不能为空".to_string())
|
||||
} else {
|
||||
// delete_local 硬编码 false:MCP 侧永不删除本地文件
|
||||
crate::commands::projects::delete_project(pid.to_string(), Some(false))
|
||||
.map(|_| format!("已删除登记:{}(本地文件未动)", pid))
|
||||
}
|
||||
}
|
||||
"ingest_git_history" => {
|
||||
let pid = args.get("project_id").and_then(|v| v.as_str());
|
||||
let conn = db::pool().get().map_err(|e| e.to_string())?;
|
||||
@ -1127,6 +1148,7 @@ mod tests {
|
||||
assert!(names.contains(&"poll_now"), "缺少 poll_now");
|
||||
assert!(names.contains(&"predict_task_risk"), "缺少 predict_task_risk");
|
||||
assert!(names.contains(&"ingest_git_history"), "缺少 ingest_git_history");
|
||||
assert!(names.contains(&"unregister_project"), "缺少 unregister_project");
|
||||
// 每个工具都有 description 和 inputSchema
|
||||
for tool in tools {
|
||||
let name = tool["name"].as_str().unwrap_or("?");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user