From 7cdcfaddb034da8c258bf47cd4788e2af0db2614 Mon Sep 17 00:00:00 2001 From: iven Date: Sat, 18 Apr 2026 22:58:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(growth):=20MEDIUM-10=20Experience=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20tool=5Fused=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: Experience 结构体没有 tool_used 字段,PatternAggregator 从 context 字段提取工具名(语义混淆),导致工具信息不准确。 修复: - experience_store.rs: Experience 添加 tool_used: Option 字段 (#[serde(default)] 兼容旧数据),Experience::new() 初始化为 None - experience_extractor.rs: persist_experiences() 从 ExperienceCandidate 的 tools_used[0] 填充 tool_used,同时填充 industry_context - pattern_aggregator.rs: 改用 tool_used 字段提取工具名,不再误用 context - store_experience() 将 tool_used 加入 keywords 提升搜索命中率 --- crates/zclaw-growth/src/experience_extractor.rs | 5 ++++- crates/zclaw-growth/src/experience_store.rs | 7 +++++++ crates/zclaw-growth/src/pattern_aggregator.rs | 5 ++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/zclaw-growth/src/experience_extractor.rs b/crates/zclaw-growth/src/experience_extractor.rs index aa277a0..332becd 100644 --- a/crates/zclaw-growth/src/experience_extractor.rs +++ b/crates/zclaw-growth/src/experience_extractor.rs @@ -45,13 +45,16 @@ impl ExperienceExtractor { Outcome::Partial => "partial", Outcome::Failed => "failed", }; - let exp = crate::experience_store::Experience::new( + let mut exp = crate::experience_store::Experience::new( agent_id, &candidate.pain_pattern, &candidate.context, candidate.solution_steps.clone(), outcome_str, ); + // 填充 tool_used:取 tools_used 中的第一个作为主要工具 + exp.tool_used = candidate.tools_used.first().cloned(); + exp.industry_context = candidate.industry_context.clone(); store.store_experience(&exp).await?; count += 1; } diff --git a/crates/zclaw-growth/src/experience_store.rs b/crates/zclaw-growth/src/experience_store.rs index ca0310c..ec6f8fe 100644 --- a/crates/zclaw-growth/src/experience_store.rs +++ b/crates/zclaw-growth/src/experience_store.rs @@ -48,6 +48,9 @@ pub struct Experience { /// Which trigger signal produced this experience. #[serde(default)] pub source_trigger: Option, + /// Primary tool/skill used to resolve this pain point. + #[serde(default)] + pub tool_used: Option, } impl Experience { @@ -72,6 +75,7 @@ impl Experience { updated_at: now, industry_context: None, source_trigger: None, + tool_used: None, } } @@ -124,6 +128,9 @@ impl ExperienceStore { if let Some(ref industry) = exp.industry_context { keywords.push(industry.clone()); } + if let Some(ref tool) = exp.tool_used { + keywords.push(tool.clone()); + } let entry = MemoryEntry { uri, diff --git a/crates/zclaw-growth/src/pattern_aggregator.rs b/crates/zclaw-growth/src/pattern_aggregator.rs index eb28c4f..4c2cd90 100644 --- a/crates/zclaw-growth/src/pattern_aggregator.rs +++ b/crates/zclaw-growth/src/pattern_aggregator.rs @@ -52,11 +52,10 @@ impl PatternAggregator { let total_reuse: u32 = experiences.iter().map(|e| e.reuse_count).sum(); let common_steps = Self::find_common_steps(&experiences); - // 从 context 字段提取工具名(context 存储的是触发工具/来源标识) - // Experience 结构没有独立的 tools 字段,context 作为来源标识使用 + // 从 tool_used 字段提取工具名 let tools: Vec = experiences .iter() - .map(|e| e.context.clone()) + .filter_map(|e| e.tool_used.clone()) .filter(|s| !s.is_empty()) .collect::>() .into_iter()