修复: BUG-260620-05 工程内路径弹窗 + G1 多目标累积 + 测试编译债
- BUG-260620-05: reload_allowed_dirs 无条件插入 workspace_root,工程内路径免授权 - G1: pinned_goal → pinned_goals Vec<String>,多目标追加去重 + MAX_GOALS=5 - tool_registry.rs 测试 4 处补 data_dir 形参 - 更新 todo.md / docs/todo.md 状态
This commit is contained in:
@@ -132,14 +132,19 @@ pub const GOAL_PIN_ENABLED: bool = true;
|
||||
/// system_prompt,无标题分隔(紧凑,排障/对比用)。
|
||||
pub const GOAL_INJECT_BANNER: bool = true;
|
||||
|
||||
/// G1 截断长度:目标文本截断上限(默认 500 字符)。
|
||||
/// G1 截断长度:每条目标文本截断上限(默认 500 字符)。
|
||||
///
|
||||
/// 防 R1 反向风险:长 user 消息(粘贴需求文档/长 bug 描述)每轮占 system_prompt 预算。
|
||||
/// system_prompt 虽不被裁剪但仍计 sys_tokens 占预算,故截断防长目标撑爆。500 保守(首版,
|
||||
/// 可调),足够覆盖正常一句话目标。截断后追加「…」省略号标识。
|
||||
pub const GOAL_MAX_CHARS: usize = 500;
|
||||
|
||||
/// G4 目标感知降级:话题标记 insert 当 pinned_goal 存在时跳过(默认 true)。
|
||||
/// G1 多目标上限:最多累积目标数(默认 5)。
|
||||
///
|
||||
/// 防无限膨胀:每次发消息提取的目标追加到 pinned_goals vec,超上限时淘汰最早目标。
|
||||
pub const MAX_GOALS: usize = 5;
|
||||
|
||||
/// G4 目标感知降级:话题标记 insert 当 pinned_goals 存在时跳过(默认 true)。
|
||||
///
|
||||
/// 治 R2(话题标记反向误导):G1 目标钉扎生效后每轮 system_prompt 已含目标,topic marker 的
|
||||
/// 「请以新话题为准」软提示成冗余且与目标矛盾(诊断 §三双锚点稀释)。true(默认)= 当
|
||||
@@ -768,49 +773,52 @@ pub(crate) async fn run_agentic_loop(
|
||||
// BUG-260617-12: DeepSeek thinking 模式推理内容跨轮透传
|
||||
let mut last_reasoning_content: Option<String> = None;
|
||||
|
||||
// G1 目标钉扎:入口把 PerConvState.pinned_goal 拼进 system_prompt 尾部(一次拼好整个 loop 复用)。
|
||||
// G1 目标钉扎:入口把 PerConvState.pinned_goals 拼进 system_prompt 尾部(一次拼好整个 loop 复用)。
|
||||
//
|
||||
// 治 R1(目标消息被压缩出局)/R5(prompt 说教无锚点):system_prompt 是 loop 不变量 + build_for_request
|
||||
// 从不裁剪它,故目标天然免疫压缩/裁剪/sanitize。本块是治 R1 的结构性根因(目标进 prompt 字符串非
|
||||
// messages 流,无 insert_at(0) 的连续 System 1214/首位锚点稀释/小预算被裁三重风险)。
|
||||
//
|
||||
// 单次 lock 读 pinned_goal clone(复用 L693-697 stop_flag 取用模式,同一 lock 块);Some 且非空 →
|
||||
// 截断到 GOAL_MAX_CHARS,按 GOAL_INJECT_BANNER 拼 banner+目标。GOAL_PIN_ENABLED=false → 整块跳过,
|
||||
// pinned_goal 永远 None(单点回退等价改动前)。拼接在 sys_tokens 估算前(sys_tokens 估算拼接后的 prompt)。
|
||||
// 单次 lock 读 pinned_goals clone(复用 stop_flag 取用模式,同一 lock 块);非空 → 逐条截断到
|
||||
// GOAL_MAX_CHARS,按 GOAL_INJECT_BANNER 拼 banner+编号列表。GOAL_PIN_ENABLED=false → 整块跳过,
|
||||
// pinned_goals 永远空 Vec(单点回退等价改动前)。拼接在 sys_tokens 估算前。
|
||||
//
|
||||
// 注:仅 run_agentic_loop 入口注入。手动压缩(ai_chat_compress_context IPC)/标题/提炼等路径不注入
|
||||
// 目标(对齐 openQuestions 决策:首版仅 agentic loop 入口拼,其他路径不动)。
|
||||
// 注:仅 run_agentic_loop 入口注入。手动压缩/标题/提炼等路径不注入目标。
|
||||
let mut system_prompt = system_prompt;
|
||||
if GOAL_PIN_ENABLED {
|
||||
let goal_opt: Option<String> = {
|
||||
let goals: Vec<String> = {
|
||||
let session = session_arc.lock().await;
|
||||
session
|
||||
.conv_read(&conv_id)
|
||||
.and_then(|c| c.pinned_goal.clone())
|
||||
.map(|c| c.pinned_goals.clone())
|
||||
.unwrap_or_default()
|
||||
};
|
||||
if let Some(goal) = goal_opt {
|
||||
let goal_text = goal.trim();
|
||||
if !goal_text.is_empty() {
|
||||
let goal_text: String = goal_text.chars().take(GOAL_MAX_CHARS).collect();
|
||||
let goal_text = if goal_text.chars().count() >= GOAL_MAX_CHARS {
|
||||
format!("{}…", goal_text)
|
||||
if !goals.is_empty() {
|
||||
let goal_lines: Vec<String> = goals.iter().enumerate().map(|(i, g)| {
|
||||
let g = g.trim();
|
||||
let truncated: String = g.chars().take(GOAL_MAX_CHARS).collect();
|
||||
let truncated = if truncated.chars().count() >= GOAL_MAX_CHARS {
|
||||
format!("{}…", truncated)
|
||||
} else {
|
||||
goal_text
|
||||
truncated
|
||||
};
|
||||
system_prompt = if GOAL_INJECT_BANNER {
|
||||
format!(
|
||||
"{}\n\n## 当前目标(全程锚定,所有动作须服务于它)\n{}",
|
||||
system_prompt, goal_text
|
||||
)
|
||||
} else {
|
||||
format!("{}\n\n{}", system_prompt, goal_text)
|
||||
};
|
||||
tracing::info!(
|
||||
conv_id = %conv_id,
|
||||
chars = goal_text.chars().count(),
|
||||
"[ai] G1 目标钉扎:已把 pinned_goal 拼进 system_prompt"
|
||||
);
|
||||
}
|
||||
format!("{}. {}", i + 1, truncated)
|
||||
}).collect();
|
||||
let goals_text = goal_lines.join("\n");
|
||||
system_prompt = if GOAL_INJECT_BANNER {
|
||||
format!(
|
||||
"{}\n\n## 当前目标(全程锚定,所有动作须服务于它们)\n{}",
|
||||
system_prompt, goals_text
|
||||
)
|
||||
} else {
|
||||
format!("{}\n\n{}", system_prompt, goals_text)
|
||||
};
|
||||
tracing::info!(
|
||||
conv_id = %conv_id,
|
||||
count = goals.len(),
|
||||
"[ai] G1 目标钉扎:已把 {} 个 pinned_goals 拼进 system_prompt",
|
||||
goals.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -879,16 +887,11 @@ pub(crate) async fn run_agentic_loop(
|
||||
return;
|
||||
}
|
||||
let conv = session.conv(&conv_id);
|
||||
// G4 目标感知降级:总是 take_topic_marker(防 marker 累积),但若 pinned_goal 存在
|
||||
// G4 目标感知降级:总是 take_topic_marker(防 marker 累积),但若 pinned_goals 非空
|
||||
// 且 TOPIC_MARKER_GOAL_AWARE → 丢弃 take 结果(返 None 跳过 insert)。
|
||||
// 一次 lock 同读 pinned_goal(避免额外加锁)。take 后丢弃不影响下一轮(marker 每 push
|
||||
// 一次 lock 同读 pinned_goals(避免额外加锁)。take 后丢弃不影响下一轮(marker 每 push
|
||||
// user 重检测生成,丢弃一次不残留)。GOAL_AWARE=false → 原样返回 marker(退旧行为)。
|
||||
let goal_active = TOPIC_MARKER_GOAL_AWARE
|
||||
&& conv
|
||||
.pinned_goal
|
||||
.as_deref()
|
||||
.map(|g| !g.trim().is_empty())
|
||||
.unwrap_or(false);
|
||||
let goal_active = TOPIC_MARKER_GOAL_AWARE && !conv.pinned_goals.is_empty();
|
||||
let marker = conv.messages.take_topic_marker();
|
||||
if goal_active && marker.is_some() {
|
||||
tracing::info!(
|
||||
@@ -1664,16 +1667,21 @@ pub(crate) async fn run_agentic_loop(
|
||||
{
|
||||
stall_warned = true;
|
||||
let goal_text = if STALL_BREAKER_GOAL_REMIND {
|
||||
let g = session_arc
|
||||
let goals = session_arc
|
||||
.lock()
|
||||
.await
|
||||
.conv_read(&conv_id)
|
||||
.and_then(|c| c.pinned_goal.clone())
|
||||
.map(|c| c.pinned_goals.clone())
|
||||
.unwrap_or_default();
|
||||
if g.trim().is_empty() {
|
||||
if goals.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("(当前目标: {})", g.trim())
|
||||
let goal_summary = goals.iter()
|
||||
.map(|g| g.trim())
|
||||
.filter(|g| !g.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.join("; ");
|
||||
format!("(当前目标: {})", goal_summary)
|
||||
}
|
||||
} else {
|
||||
String::new()
|
||||
|
||||
Reference in New Issue
Block a user