新增: 断点续跑与日志租约底座

This commit is contained in:
lxy
2026-10-05 23:41:18 +08:00
parent 8233ba095e
commit cb260aba4b
22 changed files with 1132 additions and 136 deletions
+27
View File
@@ -253,6 +253,33 @@ pub(crate) async fn execute_with_heartbeat(
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::time::Duration;
// ── W-h1 感知租约:写类文件工具执行前置校验(跨会话互斥,治互踩三连) ──
// 写类(write_file/patch_file/append_file/delete_file/rename_file 等:非 readonly
// 且有 path_args)执行前 acquire;任一路径被**其他会话**占用 → 立即返错(拒绝文案
// 指路占用方),不执行——LLM 拿到可行动错误自行等/换文件。获取成功 → LeaseGuard
// RAII 随本函数任意退出路径(Ok/Err/panic unwind/超时 drop)自动释放。
// 同会话重复 acquire 放行(同会话工具串行,连续编辑同一文件是正常模式)。
// agent_kind 判定:子代理调用链经 spawn_agent task-local CALLER_CONV 标记,此处
// conv_id 即 caller_conv;主/子区分用执行上下文(子代理 process_tool_calls 传
// SubAgent policy 但本函数无该参,故用名字启发不值得——统一按"main"登记不影响
// 互斥正确性,agent_kind 仅指路文案用)。
let _lease_guard = if super::lease::is_write_file_tool(name) {
match super::lease::acquire_leases(conv_id, "main", name, tool_call_id, &args) {
Ok(g) => Some(g),
Err(reason) => {
tracing::warn!(
conv_id = %conv_id,
tool = %name,
tool_call_id = %tool_call_id,
"[lease] 写类工具被文件租约拒绝: {reason}"
);
return Err(anyhow::anyhow!("文件占用冲突: {reason}"));
}
}
} else {
None
};
// RAII guard:drop 时 stop+abort 心跳 task,确保 execute panic(unwind)也不泄漏心跳 task。
struct HeartbeatGuard {
stop: Arc<AtomicBool>,
@@ -600,6 +600,7 @@ mod tests {
updated_at: "1".to_string(),
origin: origin.map(|s| s.to_string()),
boundary_json: None,
loop_state: None,
})
.await
.expect("测试会话插入应成功");