From cad76ffdf2d8c3c49753854eef1b0a5e40c4e5b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com> Date: Sun, 9 Aug 2026 21:34:52 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20@=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E8=81=94=E6=83=B3=E6=BA=90=E9=9A=94=E7=A6=BB=20store.tasks=20?= =?UTF-8?q?=E6=B1=A1=E6=9F=93=20+=20DirAuthDialog=20=E6=8B=92=E7=BB=9D?= =?UTF-8?q?=E4=BA=8C=E6=AC=A1=E7=A1=AE=E8=AE=A4=20+=20=E7=9C=8B=E6=9D=BF?= =?UTF-8?q?=E9=94=80=E8=B4=A6(AC=E5=BC=B1=E6=A8=A1=E5=9E=8B=E6=9C=BA?= =?UTF-8?q?=E5=88=B6=203/5=20=E5=B7=B2=E8=90=BD=E5=9C=B0=E6=A0=B8=E5=AF=B9?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/todo.md | 20 ++++++++++---------- src/components/ai/ChatInput.vue | 19 +++++++++++++++++-- src/components/ai/DirAuthDialog.vue | 21 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/docs/todo.md b/docs/todo.md index 6b95454..1b8059b 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -385,11 +385,11 @@ graph TD - [x] ✅ **P1-a** 长内容折叠(MessageList AI 文本气泡>1500 字 + ConflictResolver 多冲突 + HelpRequiredCard 堆栈,`9e85cad`) - [x] ✅ **P1-b** Dashboard 统计源解耦(治 H6/H7 翻页/筛选后统计错乱;统计走后端 count_tasks 独立通道,`d1321af`) -- [ ] **P1-c** 列表状态持久化(抽 `usePersistedRef` composable + Tasks/Ideas/Knowledge/Projects/ProjectDetail Tab 接入) -- [ ] **P1-d** AuditLog 后端 WHERE 筛选 + 真实 total + 前端持久化(治"客户端筛选只作用当前页 50 条"假象) -- [ ] **P1-e** 审批体系一致(ApprovalPopup 浮窗挂起计时 H1 + 授权粒度统一 ToolCard/Popup/DirAuthDialog + 拒绝二次确认 + 失败 toast) -- [ ] **P1-f** cmd 闪烁 N²(FileTree 展开缓存 git status,避免每次全仓扫描) -- [ ] **P1-g** 延伸:ProjectDetail.vue:368 + ChatInput.vue:367 同源 `store.tasks.filter` 污染(项目任务展示 / @ 联想,P1-b 核查时发现) +- [x] ✅ **P1-c** 列表状态持久化 — **2026-08-09 核验销账**:usePersistedRef 已接入 Tasks/Projects/Knowledge/Ideas/AuditLog;ProjectDetail Tab 手写 localStorage 按 projectId 隔离(动态 key,usePersistedRef 静态 key 不适用)保留 +- [x] ✅ **P1-d** AuditLog 后端 WHERE 筛选 + 真实 total — **2026-08-09 核验销账**:list_tool_executions(record.rs:182)支持 status/risk_level/tool_keyword WHERE + count_by_query 独立 COUNT 真实 total + limit/offset 分页;前端 AuditLog.vue buildQuery 传后端 + usePersistedRef 持久化 +- [~] **P1-e** 审批体系一致 — **部分(2026-08-09 核验)**:挂起计时✅(ApprovalPopup :191 MM:SS)/ 授权粒度统一✅(ToolCard/ApprovalPopup/DirAuthDialog 同 i18n)/ deny 二次确认✅(本批补 DirAuthDialog)/ **失败 toast 🟡待设计**(ApprovalPopup runApproval 乐观移除且 catch 仅 console.error;useAiApproval 失败仅气泡无 toast,需设计 toast 接入) +- [~] **P1-f** cmd 闪烁 N² — **部分(2026-08-09 核验)**:前端展开缓存已做(FileExplorer loadedChildren 去重);**后端每次展开新目录仍整仓 git status 扫描(module.rs:654)待架构级缓存,登记待设计** +- [x] ✅ **P1-g** store.tasks.filter 污染 — **2026-08-09 核验+补全销账**:ProjectDetail 独立 taskApi.list 已修;ChatInput @项目 enrichment 独立拉取(projectTasksCache)已修 + @任务联想本批改独立全量缓存 taskSuggestionCache(隔离 Tasks 页筛选子集)+ mentionTotal 对齐 **P2(打磨)**:幽灵 `--df-primary` / git 状态色 token / 控件统一(原问题 8 延伸)/ 死代码清理(PlanProgress/isLastUser) @@ -403,11 +403,11 @@ graph TD > 实证:prod(76 会话/9928 消息/6392 工具)+ dev(98 会话/7853 消息)库 + 会话 dump 反推。详单 [aichat历史会话实证诊断-2026-08-04.md](./05-代码审查/aichat历史会话实证诊断-2026-08-04.md)。 > 核心:弱模型(sensenova-6.7-flash-lite)在任务中**重复探索/绕工具/参数错误**是系统性现象,非偶发。 -- [ ] **AC-1** 机制层「同参数重复调用」拦截:同会话同工具同参数组 ≥2 次即返缓存/警告(现仅 prompt.rs:107 说教,弱模型无效;**实证 83 个重复组合 ≥3 次**,09e7abfa 同一文件读 6 次、e0b5d8fc update_task 同参 8 次) -- [ ] **AC-2** 探索预算上限:单轮工具调用数上限 + 目录列举去重 + list_directory 后禁止绕 run_command 同探(09e7abfa 同一目录列 3 次再 Get-ChildItem 绕行) -- [ ] **AC-3** 系统 prompt 项目清单补 UUID(prompt.rs:304 注入 `- {name}: {desc}` 无 id):**实证 list_tasks("DevFlow"/"meta-kit"/"u-ask") 12+ 处传 name 当 id 全返空** -- [ ] **AC-4** read_symbol 采用率诊断:**实证 read_file 2582 vs read_symbol 36(采用率 1.4%)**,AST 代码智能(7c2e3b2)落地空转,prompt 引导对弱模型无效,需机制(read_file 命中已知符号时提示换 read_symbol / 按模型分级) -- [ ] **AC-5** 失败工具画像复盘:run_command 67 / read_file 55 / search_files 33 / advance_task 31(状态机拒) / patch_file 27,逐类找机制根因降失败 +- [x] **AC-1** ✅ 已落地(2026-08-09 核验):双层拦截——调用级 `cache.rs:251 find_cached_readonly_result`(同 tool_name+canonical_args 已 completed 即返缓存+警告头,第 2 次即命中)+ 轮级 `is_repetitive_exploration`(helpers.rs:304-332,单签名≥3/唯一率<40%)→ `check_stall_breaker`(警示→硬熔断 emit AiHelpRequired) +- [x] **AC-2** ✅ 已落地(2026-08-09 核验,提交 fe780c0):`MAX_TOOL_CALLS_PER_ROUND=8`(agentic/mod.rs:245)+ 目录列举去重(readonly_cache_args_key 只取 path,返目录专用警告)+ `detect_listing_bypass`(run_command 含列举命令且引用已列目录→警告,保守式不硬拒) +- [x] **AC-3** ✅ 已落地(2026-08-09 核验):prompt.rs:304/323 项目/任务清单已含 id + 注明语(projects_listed_note "引用用 id 非名称");**兜底机制超要求**:entity_resolve.rs name→id 自动解析(RESOLVE_MAP 12 工具 + UUID 跳过 + 0 命中/重名返可行动错误 + 9 单测,audit/mod.rs process_tool_calls 单点漏斗) +- [~] **AC-4** 🟡 部分(2026-08-09 核验):read_file 结果级提示已落地(tools/file.rs:185-197,支持语言集内追加"改用 read_symbol")+ 三态本体(code_intel.rs:130)+ 缓存兜底;**缺口**:无按模型分级、无符号级命中检测、无采用率回测(prompt 引导对弱模型仍偏弱,待评估) +- [~] **AC-5** 🟡 部分(2026-08-09 核验):画像复盘已做(docs/AI工具失败画像复盘-2026-08-08.md)+ 2/5 自愈机制落地(advance_task legal_targets 回灌 task_state_machine.rs:121 / patch_file 相近锚点 file.rs:552);**缺口**:无运行时按工具失败率统计机制(read_file 相近文件候选、search_files 空结果引导为复盘建议未落地,待评估) ### 💡 2026-08-04 MCP 多进程架构潜在问题(分析登记) diff --git a/src/components/ai/ChatInput.vue b/src/components/ai/ChatInput.vue index 197b2f9..3341439 100644 --- a/src/components/ai/ChatInput.vue +++ b/src/components/ai/ChatInput.vue @@ -346,6 +346,8 @@ function detectMentionTrigger() { mentionStart.value = i mentionOpen.value = true mentionIndex.value = 0 + // P1-g: 用户首次进入 @ 联想即懒加载全量任务候选(幂等,缓存判重;不在 computed 副作用内调用) + void ensureTaskSuggestions() return } // 形如 a@b:前字符非空白 → 不是 mention 触发符,继续向前扫也只会找到更早的 @, @@ -403,6 +405,19 @@ const pendingMentionSpans = ref([]) const MENTION_TASK_LIMIT = 50 const projectTasksCache = ref>(new Map()) +// P1-g: @任务联想候选源隔离 store.tasks(反映 Tasks 视图筛选+分页子集)。 +// 懒加载全量未删任务(taskApi.list() 无参=全量)+ 缓存;首次 @ 触发拉取,失败空数组占位防反复重试。 +const taskSuggestionCache = ref(null) +async function ensureTaskSuggestions(): Promise { + if (taskSuggestionCache.value) return + try { + taskSuggestionCache.value = await taskApi.list() + } catch (e) { + taskSuggestionCache.value = [] + console.error('[ChatInput] 加载任务联想失败:', e) + } +} + /** 拉取指定项目的任务并缓存(已缓存则跳过);失败静默降级为空数组(不阻塞 enrichment 渲染) */ async function ensureProjectTasks(projectId: string): Promise { if (projectTasksCache.value.has(projectId)) return @@ -564,7 +579,7 @@ const mentionQuery = computed(() => { const mentionItems = computed(() => { const q = mentionQuery.value.trim().toLowerCase() const projects = (projectsStore.projects || []) as ProjectRecord[] - const tasks = (projectsStore.tasks || []) as TaskRecord[] + const tasks = (taskSuggestionCache.value ?? []) as TaskRecord[] const match = (s: string) => !q || s.toLowerCase().includes(q) const projectItems: MentionItem[] = projects .filter(p => match(p.name) || match(p.description || '')) @@ -606,7 +621,7 @@ const mentionItems = computed(() => { /** 联想候选总数(未过滤,用于区分"无匹配" vs "空") */ const mentionTotal = computed(() => ((projectsStore.projects || []) as ProjectRecord[]).length - + ((projectsStore.tasks || []) as TaskRecord[]).length + + (taskSuggestionCache.value?.length ?? 0) + ((projectsStore.ideas || []) as IdeaRecord[]).length, ) diff --git a/src/components/ai/DirAuthDialog.vue b/src/components/ai/DirAuthDialog.vue index 87102f8..8495a2b 100644 --- a/src/components/ai/DirAuthDialog.vue +++ b/src/components/ai/DirAuthDialog.vue @@ -37,6 +37,13 @@ >{{ $t('aiChat.dirAuthDeny') }} + +