diff --git a/src-tauri/src/mcp_tools.rs b/src-tauri/src/mcp_tools.rs index 5e9a4b7..6530389 100644 --- a/src-tauri/src/mcp_tools.rs +++ b/src-tauri/src/mcp_tools.rs @@ -57,6 +57,14 @@ pub fn tools_list_result() -> Value { "required": ["project_id"] } }, + { + "name": "list_envoy_returns", + "description": "列出所有子项目通过「炼境使者」发回炼境的待处理洞察,按项目分组展示。炼境会话启动时调用,用于检查是否有需要处置的治理反馈(模板 bug、验证有效的实践、体系改进假设)。无需任何参数。", + "inputSchema": { + "type": "object", + "properties": {} + } + }, { "name": "append_project_note", "description": "将 Claude 的分析结论或复盘记录写入项目笔记,供未来会话和用户在炼境中查阅。完成 M/L 复杂度任务后必须调用,写入结构化复盘笔记。", @@ -370,6 +378,9 @@ pub async fn tools_call(params: Option<&Value>) -> Value { let pid = args.get("project_id").and_then(|v| v.as_str()).unwrap_or(""); get_project_mentor_context(pid) } + "list_envoy_returns" => { + list_envoy_returns() + } "append_project_note" => { let pid = args.get("project_id").and_then(|v| v.as_str()).unwrap_or(""); let content = args.get("content").and_then(|v| v.as_str()).unwrap_or(""); @@ -887,6 +898,46 @@ fn get_project_mentor_context(project_id: &str) -> Result { Ok(ctx.mentor_markdown) } +fn list_envoy_returns() -> Result { + let conn = db::pool().get().map_err(|e| e.to_string())?; + let mut stmt = conn + .prepare( + "SELECT pn.id, pp.name, pn.content, pn.created_at + FROM project_notes pn + JOIN project_workspaces pw ON pn.project_id = pw.id + JOIN project_profiles pp ON pw.profile_id = pp.id + WHERE pn.content LIKE '【炼境使者回传】%' + ORDER BY pn.created_at DESC + LIMIT 50", + ) + .map_err(|e| e.to_string())?; + + let rows: Vec<(i64, String, String, String)> = stmt + .query_map([], |row| { + Ok(( + row.get::<_, i64>(0)?, + row.get::<_, String>(1)?, + row.get::<_, String>(2)?, + row.get::<_, String>(3)?, + )) + }) + .map_err(|e| e.to_string())? + .filter_map(|r| r.ok()) + .collect(); + + if rows.is_empty() { + return Ok("📭 暂无待处理的炼境使者回传".to_string()); + } + + let mut out = format!("📬 炼境使者回传(共 {} 条)\n\n", rows.len()); + for (_id, project_name, content, created_at) in &rows { + let date = &created_at[..created_at.len().min(10)]; + out.push_str(&format!("---\n**来源**: {} | **时间**: {}\n{}\n\n", project_name, date, content)); + } + out.push_str("---\n💡 处置参考:fix_template → 改接入包模板文件;update_convention → 改 CONVENTIONS.md;log_for_review → 记录待观察,暂不动模板"); + Ok(out) +} + fn append_project_note(project_id: &str, content: &str) -> Result { if content.trim().is_empty() { return Err("笔记内容不能为空".to_string());