Skip to content

Commit 2bf9270

Browse files
authored
Fix multiple turn-checkpoints issue (#3063)
- Add -f flag to git tag to allow overwriting existing tags - Move turn checkpoints to end of list when updating to maintain correct chronological ordering - Update turn checkpoint after each tool use to point to latest state - Fix expand functionality to show correct tool checkpoints for each turn
1 parent 115417f commit 2bf9270

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

crates/chat-cli/src/cli/chat/checkpoint.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,28 @@ impl CheckpointManager {
171171
tool_name,
172172
};
173173

174-
self.checkpoints.push(checkpoint);
175-
self.tag_index.insert(tag.to_string(), self.checkpoints.len() - 1);
174+
// Check if checkpoint with this tag already exists
175+
if let Some(&existing_idx) = self.tag_index.get(tag) {
176+
if is_turn {
177+
// For turn checkpoints, always move to the end to maintain correct ordering
178+
self.checkpoints.remove(existing_idx);
179+
180+
// Update all indices in tag_index that are greater than the removed index
181+
for (_, index) in self.tag_index.iter_mut() {
182+
if *index > existing_idx {
183+
*index -= 1;
184+
}
185+
}
186+
187+
// Add the updated checkpoint at the end
188+
self.checkpoints.push(checkpoint);
189+
self.tag_index.insert(tag.to_string(), self.checkpoints.len() - 1);
190+
}
191+
} else {
192+
// Add new checkpoint
193+
self.checkpoints.push(checkpoint);
194+
self.tag_index.insert(tag.to_string(), self.checkpoints.len() - 1);
195+
}
176196

177197
// Cache file stats for this checkpoint
178198
if let Ok(stats) = self.compute_file_stats(tag) {
@@ -404,7 +424,7 @@ fn stage_commit_tag(shadow_path: &str, work_tree: &Path, message: &str, tag: &st
404424
}
405425

406426
// Tag
407-
let output = run_git(Path::new(shadow_path), None, &["tag", tag])?;
427+
let output = run_git(Path::new(shadow_path), None, &["tag", tag, "-f"])?;
408428
if !output.status.success() {
409429
bail!(
410430
"Checkpoint initialization failed: {}",

crates/chat-cli/src/cli/chat/mod.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2321,7 +2321,7 @@ impl ChatSession {
23212321
};
23222322
let tag = if has_changes {
23232323
// Generate tag for this tool use
2324-
let tag = format!("{}.{}", manager.current_turn + 1, manager.tools_in_turn + 1);
2324+
let tool_tag = format!("{}.{}", manager.current_turn + 1, manager.tools_in_turn + 1);
23252325

23262326
// Get tool summary for commit message
23272327
let is_fs_read = matches!(&tool.tool, Tool::FsRead(_));
@@ -2334,9 +2334,9 @@ impl ChatSession {
23342334
}
23352335
};
23362336

2337-
// Create checkpoint
2337+
// Create tool checkpoint
23382338
if let Err(e) = manager.create_checkpoint(
2339-
&tag,
2339+
&tool_tag,
23402340
&description,
23412341
&self.conversation.history().clone(),
23422342
false,
@@ -2346,7 +2346,23 @@ impl ChatSession {
23462346
None
23472347
} else {
23482348
manager.tools_in_turn += 1;
2349-
Some(tag)
2349+
2350+
// Also update/create the turn checkpoint to point to latest state
2351+
// This is important so that we create turn-checkpoints even when tools are aborted
2352+
let turn_tag = format!("{}", manager.current_turn + 1);
2353+
let turn_description = "Turn in progress".to_string();
2354+
2355+
if let Err(e) = manager.create_checkpoint(
2356+
&turn_tag,
2357+
&turn_description,
2358+
&self.conversation.history().clone(),
2359+
true,
2360+
None,
2361+
) {
2362+
debug!("Failed to update turn checkpoint: {}", e);
2363+
}
2364+
2365+
Some(tool_tag)
23502366
}
23512367
} else {
23522368
None

0 commit comments

Comments
 (0)