修复策划工具乱序局部修改导致的中断
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
按原文位置排序并顺序拼接补丁,避免替换偏移失效。 新增乱序、中文与长度变化的局部修改回归测试。 同步策划 Agent 批量局部修改技术说明。
This commit is contained in:
@@ -380,11 +380,16 @@ pub(crate) fn execute_design_file_tool(
|
||||
}
|
||||
return Err(details.join("\n"));
|
||||
}
|
||||
let mut updated = content.clone();
|
||||
for (index, start, end) in matches.into_iter().rev() {
|
||||
matches.sort_unstable_by_key(|(_, start, _)| *start);
|
||||
let mut updated = String::with_capacity(content.len());
|
||||
let mut cursor = 0;
|
||||
for (index, start, end) in matches {
|
||||
let (_, new) = &normalized[index];
|
||||
updated.replace_range(start..end, new);
|
||||
updated.push_str(&content[cursor..start]);
|
||||
updated.push_str(new);
|
||||
cursor = end;
|
||||
}
|
||||
updated.push_str(&content[cursor..]);
|
||||
if updated == content {
|
||||
return Err(format!("没有产生修改:{display}"));
|
||||
}
|
||||
@@ -834,6 +839,35 @@ mod tests {
|
||||
assert!(!root.join("design_artifacts/notes").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn patch_file_applies_out_of_order_edits_with_changing_utf8_lengths() {
|
||||
let temp = test_root();
|
||||
let root = temp.path();
|
||||
execute_design_file_tool(
|
||||
root,
|
||||
"write_file",
|
||||
&json!({"path":"notes/design.md","content":"开头\n甲\n保留一\n乙乙\n保留二\n丙\n结尾"}),
|
||||
)
|
||||
.expect("write");
|
||||
execute_design_file_tool(
|
||||
root,
|
||||
"patch_file",
|
||||
&json!({
|
||||
"path":"notes/design.md",
|
||||
"edits":[
|
||||
{"old_text":"丙","new_text":"新的结论"},
|
||||
{"old_text":"甲","new_text":"扩展A"},
|
||||
{"old_text":"乙乙","new_text":"乙"}
|
||||
]
|
||||
}),
|
||||
)
|
||||
.expect("patch out of order");
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("design_artifacts/notes/design.md")).expect("read disk"),
|
||||
"开头\n扩展A\n保留一\n乙\n保留二\n新的结论\n结尾"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn phase_context_injects_current_skill_only() {
|
||||
let resources = DesignResources::new(pack_root()).expect("pack");
|
||||
|
||||
Reference in New Issue
Block a user