pub fn offer_resume_if_checkpoint_exists(
args: &crate::cli::Args,
config: &Config,
registry: &AgentRegistry,
logger: &Logger,
developer_agent: &str,
reviewer_agent: &str,
workspace: &dyn Workspace,
) -> Option<ResumeResult> {
if args.recovery.resume {
return None;
}
if args.recovery.no_resume {
return None;
}
if crate::app::env_access::check_no_resume_prompt() {
return None;
}
if !can_prompt_user() {
return None;
}
if !checkpoint_exists_with_workspace(workspace) {
return None;
}
let checkpoint = match load_checkpoint_with_workspace(workspace) {
Ok(Some(cp)) => cp,
Ok(None) => return None,
Err(e) => {
logger.warn(&format!("Checkpoint exists but failed to load: {e}"));
return None;
}
};
logger.header("FOUND PREVIOUS RUN", crate::logger::Colors::cyan);
display_user_friendly_checkpoint_summary(&checkpoint, logger);
if !prompt_user_to_resume(logger) {
logger.info("Deleting checkpoint and starting fresh...");
let _ = crate::checkpoint::clear_checkpoint_with_workspace(workspace);
return None;
}
logger.header("RESUME: Loading Checkpoint", crate::logger::Colors::yellow);
let validation = validate_checkpoint(&checkpoint, config, registry, workspace);
validation.warnings.iter().for_each(|warning| {
logger.warn(warning);
});
validation.errors.iter().for_each(|error| {
logger.error(error);
});
if !validation.is_valid {
logger.error("Checkpoint validation failed. Cannot resume.");
logger.info("Delete .agent/checkpoint.json and start fresh, or fix the issues above.");
return None;
}
if checkpoint.developer_agent != developer_agent {
logger.warn(&format!(
"Developer agent changed: {} -> {}",
checkpoint.developer_agent, developer_agent
));
}
if checkpoint.reviewer_agent != reviewer_agent {
logger.warn(&format!(
"Reviewer agent changed: {} -> {}",
checkpoint.reviewer_agent, reviewer_agent
));
}
check_rebase_state_on_resume(&checkpoint, logger);
let validation_outcome = checkpoint.file_system_state.as_ref().map_or(
ValidationOutcome::Passed,
|file_system_state| {
validate_file_system_state(
file_system_state,
logger,
args.recovery.recovery_strategy.into(),
workspace,
)
},
);
if matches!(validation_outcome, ValidationOutcome::Failed(_)) {
return None;
}
Some(ResumeResult { checkpoint })
}
fn can_prompt_user() -> bool {
crate::app::env_access::is_terminal_io()
}
fn prompt_user_to_resume(logger: &Logger) -> bool {
crate::app::terminal::prompt_yes_no(logger, "Would you like to resume from where you left off?")
}