use crate::workspace::Workspace;
#[derive(Clone)]
pub struct InterruptContext {
pub phase: crate::checkpoint::PipelinePhase,
pub iteration: u32,
pub total_iterations: u32,
pub reviewer_pass: u32,
pub total_reviewer_passes: u32,
pub run_context: crate::checkpoint::RunContext,
pub execution_history: crate::checkpoint::ExecutionHistory,
pub prompt_history: std::collections::HashMap<String, crate::prompts::PromptHistoryEntry>,
pub workspace: std::sync::Arc<dyn Workspace>,
}
pub(super) fn save_interrupt_checkpoint(context: &InterruptContext) -> anyhow::Result<()> {
use crate::checkpoint::state::{
calculate_file_checksum_with_workspace, AgentConfigSnapshot, CheckpointParams,
CliArgsSnapshotBuilder, PipelineCheckpoint, RebaseState,
};
use crate::checkpoint::{load_checkpoint_with_workspace, save_checkpoint_with_workspace};
use std::path::Path;
if let Ok(Some(checkpoint)) = load_checkpoint_with_workspace(&*context.workspace) {
let checkpoint = PipelineCheckpoint {
phase: context.phase,
iteration: context.iteration,
total_iterations: context.total_iterations,
reviewer_pass: context.reviewer_pass,
total_reviewer_passes: context.total_reviewer_passes,
actual_developer_runs: context.run_context.actual_developer_runs,
actual_reviewer_runs: context.run_context.actual_reviewer_runs,
execution_history: Some(context.execution_history.clone()),
prompt_history: Some(context.prompt_history.clone()),
interrupted_by_user: true,
..checkpoint
};
save_checkpoint_with_workspace(&*context.workspace, &checkpoint)?;
} else {
let prompt_md_checksum =
calculate_file_checksum_with_workspace(&*context.workspace, Path::new("PROMPT.md"))
.or_else(|| Some("unknown".to_string()));
let cli_args = CliArgsSnapshotBuilder::new(
context.total_iterations,
context.total_reviewer_passes,
None,
true,
)
.build();
let developer_agent = "unknown";
let reviewer_agent = "unknown";
let developer_agent_config = AgentConfigSnapshot::new(
developer_agent.to_string(),
"unknown".to_string(),
"-o".to_string(),
None,
true,
);
let reviewer_agent_config = AgentConfigSnapshot::new(
reviewer_agent.to_string(),
"unknown".to_string(),
"-o".to_string(),
None,
true,
);
let working_dir = context.workspace.root().to_string_lossy().to_string();
let base_checkpoint = PipelineCheckpoint::from_params(CheckpointParams {
phase: context.phase,
iteration: context.iteration,
total_iterations: context.total_iterations,
reviewer_pass: context.reviewer_pass,
total_reviewer_passes: context.total_reviewer_passes,
developer_agent,
reviewer_agent,
cli_args,
developer_agent_config,
reviewer_agent_config,
rebase_state: RebaseState::default(),
git_user_name: None,
git_user_email: None,
run_id: &context.run_context.run_id,
parent_run_id: context.run_context.parent_run_id.as_deref(),
resume_count: context.run_context.resume_count,
actual_developer_runs: context.run_context.actual_developer_runs,
actual_reviewer_runs: context.run_context.actual_reviewer_runs,
working_dir,
prompt_md_checksum,
config_path: None,
config_checksum: None,
});
let checkpoint = PipelineCheckpoint {
execution_history: Some(context.execution_history.clone()),
prompt_history: Some(context.prompt_history.clone()),
interrupted_by_user: true,
..base_checkpoint
};
save_checkpoint_with_workspace(&*context.workspace, &checkpoint)?;
}
Ok(())
}