From f82dd8ba90dea49f1b02f5cb55ec8cd71246af49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Sun, 14 Jun 2026 22:13:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E:=20Wave8=20F-06=20=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E9=A1=B9=E7=9B=AE=20+=20F-02=20=E6=8A=80=E8=83=BD?= =?UTF-8?q?=E8=81=94=E6=83=B3=20+=20AR-6=20Low=20=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E8=AF=AD=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - F-06 导入历史项目:scan.rs extract_description(README 首段 200 字) + import_project 命令(合并 create+bind,spawn_blocking 探测栈) + 前端 ProjectDetail 导入按钮 + store action;主代理补 lib.rs invoke_handler 注册(agent 未注册) - F-02 技能联想使用:核对发现 sendMessage→ai_chat_send skill 调用链已完整(联想选中→带 skill→注入 SKILL.md),补 Esc 取消选中兜底 - AR-6 Low 失败语义统一(定向B):audit.rs Low 失败 emit AiToolCallCompleted(错误 result) 替代 AiError,消除前端 false/后端 loop 续紊乱,错误回填 tool_result 让 LLM 自处理 cargo/vue-tsc 0 err --- crates/df-project/src/scan.rs | 82 ++++++++++++++++++++++++++ src-tauri/src/commands/ai/audit.rs | 13 +++- src-tauri/src/commands/project.rs | 95 +++++++++++++++++++++++++++++- src-tauri/src/lib.rs | 1 + src/api/project.ts | 17 ++++++ src/components/AiChat.vue | 6 ++ src/stores/project.ts | 15 ++++- src/views/ProjectDetail.vue | 24 ++++++++ 8 files changed, 248 insertions(+), 5 deletions(-) diff --git a/crates/df-project/src/scan.rs b/crates/df-project/src/scan.rs index 1fe86cc..847d96d 100644 --- a/crates/df-project/src/scan.rs +++ b/crates/df-project/src/scan.rs @@ -126,6 +126,51 @@ fn has_file_with_ext(dir: &Path, ext: &str) -> bool { // 项目采样(供 LLM 分析基础信息) — 纯 IO,控 token 不读源码 // ============================================================ +/// 提取项目描述 — 读 README 首段(首个非标题非空段落,截断 200 字)。 +/// +/// 用于「导入历史项目」时自动填充 description。无 README 或解析失败返回 None。 +/// 首段定义:跳过开头标题行(# / ## …)、空行、HTML 注释与 badge 图片/HTML 行等噪声, +/// 取首个含实质文本的段落(连续多行直到空行);按字符截断至 200 字避免超长。 +pub fn extract_description(root: &Path) -> Option { + // 复用 read_readme 的查找逻辑(支持 README.md / README.zh.md 等变体) + let content = read_readme(root)?; + let mut text = String::new(); + let mut started = false; + for raw_line in content.lines() { + let line = raw_line.trim(); + if line.is_empty() { + if started { + break; // 段落结束 + } + continue; // 首段尚未开始,跳过开头空行 + } + // 段落开始后不再跳行,直接累加 + if !started { + // 跳过标题 / HTML 注释 / badge 图片 / HTML 标签等噪声前导行 + if line.starts_with('#') + || line.starts_with("