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

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
+18 -1
View File
@@ -393,6 +393,16 @@ pub fn register(
anyhow::bail!("写入内容超过 1MB 限制 ({} 字节)", bytes.len());
}
let target = std::path::Path::new(path);
// R12(2026-10-05):读取旧内容供 diff 回看(仅 utf-8 且旧文件存在且 ≤1MB;
// base64 二进制/新建文件无 diff 语义,跳过。读取在写入前完成,与 rename 不竞态)
let old_content_for_diff: Option<String> = if encoding.eq_ignore_ascii_case("utf-8") {
match tokio::fs::read_to_string(target).await {
Ok(s) if s.len() <= 1_048_576 => Some(s),
_ => None,
}
} else {
None
};
// FR-S7 覆盖防护:覆盖非空文件前自动 .bak 备份(防 LLM 误用 write_file 当 edit 致数据彻底丢失)
// 起因:会话 3473fcb7 AI 误传头部 3 行把 PROGRESS.md 762 行/72KB 覆盖成 248 字节
let old_size: Option<u64> = match tokio::fs::metadata(target).await {
@@ -438,7 +448,14 @@ pub fn register(
tracing::warn!("write_file 疑似误覆盖: {} {}→{} 字节(缩减>90%),.bak 已备份", path, old, bytes.len());
}
}
Ok(serde_json::json!({ "path": path, "bytes_written": bytes.len(), "old_size": old_size, "encoding": encoding }))
// R12:行级 unified diff(旧 vs 新,同 patch_file 的 generate_diff;新建文件/base64 为 null 前端不渲染)
let diff_json = match old_content_for_diff {
Some(old) if encoding.eq_ignore_ascii_case("utf-8") => {
serde_json::Value::String(generate_diff(&old, &raw))
}
_ => serde_json::Value::Null,
};
Ok(serde_json::json!({ "path": path, "bytes_written": bytes.len(), "old_size": old_size, "encoding": encoding, "diff": diff_json }))
}
);
@@ -106,7 +106,7 @@ pub(crate) fn caller_conv() -> Option<String> {
// ── 参数解析与任务书组装(纯函数,单测锁定) ──
/// 解析 max_rounds:缺省默认 6,合法域钳制 [1, 20](防参数放大预算失控)。
/// 解析 max_rounds:缺省默认 12,合法域钳制 [1, 20](防参数放大预算失控)。
fn parse_max_rounds(raw: Option<u64>) -> u32 {
raw.map(|v| v as u32)
.unwrap_or(SUB_AGENT_DEFAULT_MAX_ROUNDS)
@@ -153,7 +153,7 @@ pub fn register(registry: &mut AiToolRegistry, ctx: SpawnAgentCtx) {
},
"max_rounds": {
"type": "integer",
"description": "可选,工具循环轮数上限,默认 6,最大 20"
"description": "可选,工具循环轮数上限,默认 12,最大 20"
},
"model": {
"type": "string",
@@ -166,7 +166,7 @@ pub fn register(registry: &mut AiToolRegistry, ctx: SpawnAgentCtx) {
registry,
ctx: SpawnAgentCtx,
"spawn_agent",
"派发一个子代理在隔离上下文中独立完成专项任务(不与用户交互),最终返回结论报告。适用:探索检索/多文件阅读汇总/资料核对等可独立收敛的子任务。参数 task 为自包含任务书(子代理看不到父对话);tools 为可选工具白名单;max_rounds 可选轮数上限(默认 6);model 可选模型(缺省继承当前会话)。注意:子代理无审批通道,写文件/命令执行等高风险工具会被自动拒绝,结论以 report 字段文本返回",
"派发一个子代理在隔离上下文中独立完成专项任务(不与用户交互),最终返回结论报告。适用:探索检索/多文件阅读汇总/资料核对等可独立收敛的子任务。参数 task 为自包含任务书(子代理看不到父对话);tools 为可选工具白名单;max_rounds 可选轮数上限(默认 12);model 可选模型(缺省继承当前会话)。注意:子代理无审批通道,写文件/命令执行等高风险工具会被自动拒绝,结论以 report 字段文本返回",
RiskLevel::Medium,
meta: ToolMeta {
// 审批卡文案模板(模板 {} 按位置填充,键取 task)