fix(growth): Evolution Engine 审计修复 — 7项全部完成
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
HIGH-1: 提取共享 json_utils.rs,skill_generator/workflow_composer 去重
HIGH-2: FeedbackCollector Vec→HashMap,消除 unwrap() panic 风险
HIGH-3: ProfileUpdater 改为 collect_updates() 返回字段列表,
growth.rs 直接 async 调用 update_field(),不再用 no-op 闭包
MEDIUM-1: EvolutionMiddleware 注入后自动 drain,防止重复注入
MEDIUM-2: PatternAggregator tools 提取改为直接收集 context 值
MEDIUM-3: evolution_engine.rs 移除 4 个未使用 imports
MEDIUM-4: workflow_composer parse_response pattern 参数加下划线
MEDIUM-7: SkillCandidate 添加 version 字段(默认=1)
测试: zclaw-growth 128 tests, zclaw-runtime 86 tests, workspace 0 failures
This commit is contained in:
@@ -15,6 +15,8 @@ pub struct SkillCandidate {
|
||||
pub body_markdown: String,
|
||||
pub source_pattern: String,
|
||||
pub confidence: f32,
|
||||
/// 技能版本号,用于后续迭代追踪
|
||||
pub version: u32,
|
||||
}
|
||||
|
||||
/// LLM 驱动的技能生成 prompt
|
||||
@@ -59,8 +61,7 @@ impl SkillGenerator {
|
||||
|
||||
/// 解析 LLM 返回的 JSON 为 SkillCandidate
|
||||
pub fn parse_response(json_str: &str, pattern: &AggregatedPattern) -> Result<SkillCandidate> {
|
||||
// 尝试提取 JSON 块(LLM 可能包裹在 ```json ... ``` 中)
|
||||
let json_str = extract_json_block(json_str);
|
||||
let json_str = crate::json_utils::extract_json_block(json_str);
|
||||
|
||||
let raw: serde_json::Value = serde_json::from_str(&json_str).map_err(|e| {
|
||||
zclaw_types::ZclawError::ConfigError(format!("Invalid skill JSON: {}", e))
|
||||
@@ -95,35 +96,11 @@ impl SkillGenerator {
|
||||
body_markdown: raw["body_markdown"].as_str().unwrap_or("").to_string(),
|
||||
source_pattern: pattern.pain_pattern.clone(),
|
||||
confidence: raw["confidence"].as_f64().unwrap_or(0.5) as f32,
|
||||
version: raw["version"].as_u64().unwrap_or(1) as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// 从 LLM 返回文本中提取 JSON 块
|
||||
fn extract_json_block(text: &str) -> &str {
|
||||
// 尝试匹配 ```json ... ```
|
||||
if let Some(start) = text.find("```json") {
|
||||
let json_start = start + 7; // skip ```json
|
||||
if let Some(end) = text[json_start..].find("```") {
|
||||
return text[json_start..json_start + end].trim();
|
||||
}
|
||||
}
|
||||
// 尝试匹配 ``` ... ```
|
||||
if let Some(start) = text.find("```") {
|
||||
let json_start = start + 3;
|
||||
if let Some(end) = text[json_start..].find("```") {
|
||||
return text[json_start..json_start + end].trim();
|
||||
}
|
||||
}
|
||||
// 尝试找 { ... } 块
|
||||
if let Some(start) = text.find('{') {
|
||||
if let Some(end) = text.rfind('}') {
|
||||
return &text[start..=end];
|
||||
}
|
||||
}
|
||||
text.trim()
|
||||
}
|
||||
|
||||
impl Default for SkillGenerator {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
@@ -194,12 +171,12 @@ mod tests {
|
||||
#[test]
|
||||
fn test_extract_json_block_with_markdown() {
|
||||
let text = "Here is the result:\n```json\n{\"key\": \"value\"}\n```\nDone.";
|
||||
assert_eq!(extract_json_block(text), "{\"key\": \"value\"}");
|
||||
assert_eq!(crate::json_utils::extract_json_block(text), "{\"key\": \"value\"}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_json_block_bare() {
|
||||
let text = "{\"key\": \"value\"}";
|
||||
assert_eq!(extract_json_block(text), "{\"key\": \"value\"}");
|
||||
assert_eq!(crate::json_utils::extract_json_block(text), "{\"key\": \"value\"}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user