优化: 狗粮短板收口与patch_file增强

- patch_file old_text 精确未中时空白归一化回退(行首缩进归一+多空白折叠,唯一命中按整行区间替换,warning 注明)
- patch_file anchor end 唯一性校验:多处命中报错并列前两处位置,治实测×2 锚点错位;三模式同传按优先级仲裁(anchor>old_text>replace_lines),warning 注明
- tool_result 压缩 memoization:PerConvState 加 tool_compress_cache(内容哈希→压缩结果),主 loop+子代理双调用点接线,治 369 组同内容反复重压
- 标题采样改两段式:user 首条必进锚定主题+其余按序补足 6 条,治 assistant 首句被当主题
- prompt 注入文件读取纪律段(父会话+子代理同源):read_file 分页/search 直读,禁 run_command 切片读文件;read_file 工具描述与 truncated 提示补大 limit 建议
- 顺带 DRY#1:agentic/mod.rs 三处裸 emit 换正典双写(心跳/破坏性回环熔断/stall 熔断),miniapp 跨端盲区补齐
This commit is contained in:
lxy
2026-10-05 00:35:04 +08:00
parent c83ea0c315
commit 6a50193b34
8 changed files with 380 additions and 79 deletions
+20 -3
View File
@@ -46,16 +46,33 @@ pub(crate) async fn ensure_conversation_title(
}
}
// 取对话文本(仅 user/assistant,跳过 tool 噪音),取前 6 条供 LLM 总结
// 取对话文本(仅 user/assistant,跳过 tool 噪音),取前 6 条供 LLM 总结。
// 狗粮实证(2026-10-04):混合 take(6) 在 assistant 消息靠前场景(重提/续接)会把 user 首条挤出,
// LLM 拿 assistant 首句当主题生成标题(如「信息已足够。让我看一眼...」)。改两段式:
// user 首条必进(锚定主题),其余按序补足 6 条。
// F-260616-09 B 批4:per_conv.messages 唯一真相源(conv_id 来源:本函数入参)。
// conv() 惰性建:switch 触发的 spawn_ensure_title 前序 switch 已 conv();若极端未建,
// conv() 建空 PerConvState → summary_msgs 空 → 下方 return(无素材不生成标题)。
let (summary_msgs, all_msgs) = {
let mut session = session_arc.lock().await;
let conv = session.conv(conv_id);
let summary: Vec<ChatMessage> = conv.messages.iter()
let sample: Vec<_> = conv.messages.iter()
.filter(|m| matches!(m.role, MessageRole::User | MessageRole::Assistant))
.take(6)
.collect();
// user 首条下标(无 user 消息则退回纯顺序 take(6),空素材由下方 return 兜住)
let first_user_idx = sample.iter().position(|m| matches!(m.role, MessageRole::User));
let mut picked: Vec<usize> = Vec::with_capacity(6);
if let Some(i) = first_user_idx {
picked.push(i);
}
for (i, _) in sample.iter().enumerate() {
if picked.len() >= 6 { break; }
if picked.contains(&i) { continue; }
picked.push(i);
}
picked.sort_unstable();
let summary: Vec<ChatMessage> = picked.into_iter()
.filter_map(|i| sample.get(i))
.map(|m| ChatMessage {
id: None, // 标题摘要派生消息:不落库不溯源,无需分配 ID(对齐老消息 None 语义)
role: m.role.clone(),