diff --git a/src-tauri/src/commands/ai/tool_registry.rs b/src-tauri/src/commands/ai/tool_registry.rs index 8e4939e..ec070f3 100644 --- a/src-tauri/src/commands/ai/tool_registry.rs +++ b/src-tauri/src/commands/ai/tool_registry.rs @@ -85,7 +85,7 @@ pub fn build_ai_tool_registry(db: &Arc) -> AiToolRegistry { let db = db.clone(); Box::pin(async move { let repo = df_storage::crud::ProjectRepo::new(&db); - let mut items = repo.list_all().await?; + let mut items = repo.list_active().await?; // list_active 排除回收站(deleted_at),防 LLM 看到已软删项目 items.truncate(50); // 防 LLM context 膨胀 Ok(serde_json::to_value(items)?) }) @@ -253,18 +253,57 @@ pub fn build_ai_tool_registry(db: &Arc) -> AiToolRegistry { // ── 高风险 (High) ── registry.register( - "delete_project", "删除项目及其所有关联数据", + "delete_project", "删除项目(移入回收站,可恢复。永久删除用 purge_project)", df_ai::ai_tools::object_schema(vec![("id", "string", true)]), RiskLevel::High, { let db = db.clone(); Box::new(move |args: serde_json::Value| { let db = db.clone(); Box::pin(async move { let id = args["id"].as_str().ok_or_else(|| anyhow::anyhow!("缺少 id"))?; let repo = df_storage::crud::ProjectRepo::new(&db); - let deleted = repo.delete(id).await?; + let deleted = repo.soft_delete(id).await?; Ok(serde_json::json!({ "deleted": deleted, "id": id })) }) })}, ); + registry.register( + "restore_project", "从回收站恢复已删除项目", + df_ai::ai_tools::object_schema(vec![("id", "string", true)]), RiskLevel::High, + { let db = db.clone(); Box::new(move |args: serde_json::Value| { + let db = db.clone(); + Box::pin(async move { + let id = args["id"].as_str().ok_or_else(|| anyhow::anyhow!("缺少 id"))?; + let repo = df_storage::crud::ProjectRepo::new(&db); + let restored = repo.restore(id).await?; + Ok(serde_json::json!({ "restored": restored, "id": id })) + }) + })}, + ); + registry.register( + "purge_project", "永久删除项目及关联数据(不可恢复)", + df_ai::ai_tools::object_schema(vec![("id", "string", true)]), RiskLevel::High, + { let db = db.clone(); Box::new(move |args: serde_json::Value| { + let db = db.clone(); + Box::pin(async move { + let id = args["id"].as_str().ok_or_else(|| anyhow::anyhow!("缺少 id"))?; + let repo = df_storage::crud::ProjectRepo::new(&db); + let purged = repo.purge_with_descendants(id).await?; + Ok(serde_json::json!({ "purged": purged, "id": id })) + }) + })}, + ); + registry.register( + "list_trash", "列出回收站已删除项目", + df_ai::ai_tools::object_schema(vec![]), RiskLevel::Low, + { let db = db.clone(); Box::new(move |_args: serde_json::Value| { + let db = db.clone(); + Box::pin(async move { + let repo = df_storage::crud::ProjectRepo::new(&db); + let mut items = repo.list_deleted().await?; + items.truncate(50); // 防 LLM context 膨胀 + Ok(serde_json::to_value(items)?) + }) + })}, + ); registry.register( "run_workflow", "运行指定的工作流 DAG", df_ai::ai_tools::object_schema(vec![("name", "string", true), ("dag", "object", true)]), RiskLevel::High,