fix(growth): 二次审计修复 — 6项 CRITICAL/HIGH/MEDIUM 全部修复
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
CRITICAL-1/2: json_utils 花括号匹配改为括号平衡算法 - 处理字符串字面量中的花括号和转义引号 - 新增 5 个测试(平衡匹配、字符串内花括号、转义引号、extract_string_array) HIGH-4: EvolutionMiddleware 只取第一个事件(remove(0)),不丢弃后续 HIGH-5: EvolutionMiddleware 先 read() 判空再 write(),减少锁竞争 HIGH-7: from_experience_store 使用传入 store 的 viking 实例(不再忽略参数) - ExperienceStore 新增 viking() getter MEDIUM-9: skill_generator + workflow_composer JSON 数组解析去重 - 新增 json_utils::extract_string_array() 共享函数 MEDIUM-14: EvolutionMiddleware 注入文本去除多余缩进空格 测试: zclaw-growth 133 tests, zclaw-runtime 87 tests, workspace 0 failures
This commit is contained in:
@@ -68,35 +68,37 @@ impl AgentMiddleware for EvolutionMiddleware {
|
||||
&self,
|
||||
ctx: &mut MiddlewareContext,
|
||||
) -> Result<MiddlewareDecision> {
|
||||
// 先用 read lock 快速判空,避免每次对话都获取写锁
|
||||
if self.pending.read().await.is_empty() {
|
||||
return Ok(MiddlewareDecision::Continue);
|
||||
}
|
||||
|
||||
// 只移除第一个事件,保留后续事件留待下次注入
|
||||
let to_inject = {
|
||||
let mut pending = self.pending.write().await;
|
||||
if pending.is_empty() {
|
||||
return Ok(MiddlewareDecision::Continue);
|
||||
}
|
||||
// 只取第一条(最近的)事件注入,避免信息过载
|
||||
// drain 已注入的事件,防止重复注入
|
||||
std::mem::take(&mut *pending)
|
||||
pending.remove(0)
|
||||
};
|
||||
|
||||
if let Some(evolution) = to_inject.into_iter().next() {
|
||||
let injection = format!(
|
||||
"\n\n<evolution-suggestion>\n\
|
||||
我注意到你经常做「{pattern}」相关的事情。\n\
|
||||
我可以帮你整理成一个技能,以后直接说「{trigger}」就能用了。\n\
|
||||
技能描述:{desc}\n\
|
||||
如果你同意,请回复 '确认保存技能'。如果你想调整,可以告诉我怎么改。\n\
|
||||
</evolution-suggestion>",
|
||||
pattern = evolution.pattern_name,
|
||||
trigger = evolution.trigger_suggestion,
|
||||
desc = evolution.description,
|
||||
);
|
||||
ctx.system_prompt.push_str(&injection);
|
||||
let injection = format!(
|
||||
"\n\n<evolution-suggestion>\n\
|
||||
我注意到你经常做「{pattern}」相关的事情。\n\
|
||||
我可以帮你整理成一个技能,以后直接说「{trigger}」就能用了。\n\
|
||||
技能描述:{desc}\n\
|
||||
如果你同意,请回复 '确认保存技能'。如果你想调整,可以告诉我怎么改。\n\
|
||||
</evolution-suggestion>",
|
||||
pattern = to_inject.pattern_name,
|
||||
trigger = to_inject.trigger_suggestion,
|
||||
desc = to_inject.description,
|
||||
);
|
||||
ctx.system_prompt.push_str(&injection);
|
||||
|
||||
tracing::info!(
|
||||
"[EvolutionMiddleware] Injected evolution suggestion for: {}",
|
||||
evolution.pattern_name
|
||||
);
|
||||
}
|
||||
tracing::info!(
|
||||
"[EvolutionMiddleware] Injected evolution suggestion for: {}",
|
||||
to_inject.pattern_name
|
||||
);
|
||||
|
||||
Ok(MiddlewareDecision::Continue)
|
||||
}
|
||||
@@ -135,4 +137,29 @@ mod tests {
|
||||
assert_eq!(mw.name(), "evolution");
|
||||
assert_eq!(mw.priority(), 78);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_only_first_event_injected() {
|
||||
let mw = EvolutionMiddleware::new();
|
||||
mw.add_pending(PendingEvolution {
|
||||
pattern_name: "事件A".to_string(),
|
||||
trigger_suggestion: "触发A".to_string(),
|
||||
description: "描述A".to_string(),
|
||||
})
|
||||
.await;
|
||||
mw.add_pending(PendingEvolution {
|
||||
pattern_name: "事件B".to_string(),
|
||||
trigger_suggestion: "触发B".to_string(),
|
||||
description: "描述B".to_string(),
|
||||
})
|
||||
.await;
|
||||
|
||||
// 模拟注入:用 read 判空 + write 取第一个
|
||||
let first = {
|
||||
let mut pending = mw.pending.write().await;
|
||||
pending.remove(0)
|
||||
};
|
||||
assert_eq!(first.pattern_name, "事件A");
|
||||
assert_eq!(mw.pending_count().await, 1); // 事件B 仍保留
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user