-
Notifications
You must be signed in to change notification settings - Fork 396
feat: Adds checkpointing functionality using Git CLI commands #2896
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Updates: - Only works if the user has git installed - Supports auto initialization if the user is in a git repo, manual if not - UI ported over from dedicated file tools implementation
Updates: - The clean subcommand will delete the shadow repo - The description for turn-level checkpoints is a truncated version of the user's last message
Updates: - Running the clean subcommand now properly deletes the entire shadow repo for both automatic and manual modes
Updates: - Users can now view diffs between checkpoints - Fixed tool-level checkpoint display handling
Updates: - Checkpoints now (hopefully) correctly display the correct turn-specific user message - Added slash command auto completion
…an-garre/git-checkpoints
| String::new() | ||
| } | ||
| // Take manager out temporarily to avoid borrow conflicts | ||
| else if let Some(mut manager) = self.conversation.checkpoint_manager.take() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any invocation here that requires a mut self for manager? If not we can just do
else if let Some(manager) = self.conversation.checkpoint_manager.as_mut() {
...
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the advise! I do change manager later (tools_in_turn += 1 and create_checkpoint also mutates internal state)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also the take() approach is here because I need to access both manager (mutably) and self.conversation.history() (immutably) in the same scope. Using as_mut() would cause a borrowing conflict when calling self.conversation.history().clone() inside create_checkpoint().
| debug!("Failed to create tool checkpoint: {}", e); | ||
| String::new() | ||
| } else { | ||
| manager.tools_in_turn += 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we ever increment this by more than one per turn? I see that we are resetting it to 0 every turn.
If that's the case this can just be a bool then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we do increase this value
It's used to generate unique checkpoint tags like "3.1", "3.2" for each tool within a turn
Multiple tools can be executed within a single turn.
We need to distinguish between different tool checkpoints in the same turn
| impl CheckpointSubcommand { | ||
| pub async fn execute(self, os: &Os, session: &mut ChatSession) -> Result<ChatState, ChatError> { | ||
| // Check if in tangent mode - captures are disabled during tangent mode | ||
| if os |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is on me but we should have an experiment helper to query experiments in particular.
| session.stderr, | ||
| style::SetForegroundColor(Color::Yellow), | ||
| style::Print( | ||
| "⚠️ Checkpoint is disabled while in tangent mode. Disable tangent mode with: q settings -d chat.enableTangentMode.\n\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why disable checkpoint if tangent mode is enabled? I understand disabling it while in Tangent mode, but not following why we can't have both features enabled at same time.
| /// Restore conversation from a checkpoint's history snapshot | ||
| pub fn restore_to_checkpoint(&mut self, checkpoint: &Checkpoint) -> Result<(), eyre::Report> { | ||
| // 1. Restore history from snapshot | ||
| self.history = checkpoint.history_snapshot.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious? Can a checkpoint corrupt conversation history by any means? Like a tool use without tool results and so on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The checkpoint is created after the tool executes successfully and in handle_response, so that should be fine. Thanks for the callout — we can test it more thoroughly during the bug bash
| session.stderr, | ||
| style::SetForegroundColor(Color::Yellow), | ||
| style::Print( | ||
| "⚠️ Checkpoint is disabled while in tangent mode. Disable tangent mode with: q settings -d chat.enableTangentMode.\n\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think user just needs to exit tangent mode, right? Doesn't need to disable it completely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. thanks for catching this. I will change the word here
* (in progress) Implement checkpointing using git CLI commands * feat: Add new checkpointing functionality using git CLI Updates: - Only works if the user has git installed - Supports auto initialization if the user is in a git repo, manual if not - UI ported over from dedicated file tools implementation * feat: Add user message for turn-level checkpoints, clean command Updates: - The clean subcommand will delete the shadow repo - The description for turn-level checkpoints is a truncated version of the user's last message * fix: Fix shadow repo deletion logic Updates: - Running the clean subcommand now properly deletes the entire shadow repo for both automatic and manual modes * chore: Run formatter and fix clippy warnings * feat: Add checkpoint diff Updates: - Users can now view diffs between checkpoints - Fixed tool-level checkpoint display handling * fix: Fix last messsage handling for checkpoints Updates: - Checkpoints now (hopefully) correctly display the correct turn-specific user message - Added slash command auto completion * fix: Fix commit message handling again * chore: Run formatter * Removed old comment * define a global capture dirctory * revise the capture path * fix cpature clean bug * add a clean all flag * add auto drop method for capture feature * support file details when expand * add the file summary when list and expand * revise structure and print no diff msg * delete all flag, add summry when fs read * refactor code * revise ui * add capture into experiement * clippy * rename to checkpoint * reverse false renaming * recover history * disable tangent mode in checkpoint * fix cr * nit: keep checkpoint name * allow both tangent & checkpoint enabled * ci --------- Co-authored-by: kiran-garre <[email protected]>
Issue #, if available:
Description of changes:
Introduce session-scoped checkpoints for the current repo. Q CLI now snapshots file changes into a shadow bare git repo and lets users list, expand, diff, and restore to any checkpoint. Errors are short and human-readable; empty diffs print “No differences.” The conversation history is also unwind when restoring a checkpoint
Commands
/checkpoint init— Manually enable checkpoints if not in a git repo./checkpoint list [--limit N]— Turn-level checkpoints with file stats./checkpoint expand <tag>— Show tool-level checkpoints under a turn, with “(+/~/-) files” badges./checkpoint diff <tag1> [tag2|HEAD]/checkpoint restore [<tag>] [--hard]<tag>omitted, shows interactive picker./checkpoint clean— Delete session shadow repo.Implementation (high-level)
Shadow storage: bare git repo under
get_shadow_repo_dir(conversation_id), operating on--work-tree=..Helper
run_git(...)centralizes--git-dir/--work-treeand error handling.File stats via
git diff --name-status; treatR/Cas modified; cache per-tag stats.Previous-tag resolution for
XandX.Yforms.Soft vs hard restore wired through
git checkoutvsgit reset --hard.Examples
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.