use crate::files::{cleanup_generated_files_with_workspace, make_prompt_writable_with_workspace};
use crate::git_helpers::{
disable_git_wrapper, end_agent_phase_in_repo, try_remove_ralph_dir, uninstall_hooks_in_repo,
verify_hooks_removed, verify_ralph_dir_removed, verify_wrapper_cleaned, GitHelpers,
};
use crate::logger::Logger;
use crate::{ChildProcessInfo, Workspace};
pub struct CommandResult {
pub(crate) exit_code: i32,
pub(crate) stderr: String,
pub session_id: Option<String>,
pub(crate) child_status_at_timeout: Option<ChildProcessInfo>,
pub(crate) timeout_context: Option<TimeoutContext>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TimeoutContext {
pub escalated: bool,
pub child_status_at_timeout: Option<ChildProcessInfo>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IdleTimeoutCause {
NoQualifying,
Stalled(ChildProcessInfo),
StaleActive(ChildProcessInfo),
}
pub struct AgentPhaseGuard<'a> {
pub git_helpers: &'a mut GitHelpers,
logger: &'a Logger,
workspace: &'a dyn Workspace,
active: bool,
}
impl<'a> AgentPhaseGuard<'a> {
pub fn new(
git_helpers: &'a mut GitHelpers,
logger: &'a Logger,
workspace: &'a dyn Workspace,
) -> Self {
Self {
git_helpers,
logger,
workspace,
active: true,
}
}
pub const fn disarm(&mut self) {
self.active = false;
}
}
impl Drop for AgentPhaseGuard<'_> {
fn drop(&mut self) {
if !self.active {
return;
}
let _ = make_prompt_writable_with_workspace(self.workspace);
let repo_root = self.workspace.root();
end_agent_phase_in_repo(repo_root);
disable_git_wrapper(self.git_helpers);
let _ = uninstall_hooks_in_repo(repo_root, self.logger);
let wrapper_remaining = verify_wrapper_cleaned(repo_root);
if !wrapper_remaining.is_empty() {
self.logger.warn(&format!(
"Wrapper artifacts still present after guard cleanup: {}",
wrapper_remaining.join(", ")
));
}
match verify_hooks_removed(repo_root) {
Ok(remaining) => {
if !remaining.is_empty() {
self.logger.warn(&format!(
"Ralph hooks still present after guard cleanup: {}",
remaining.join(", ")
));
}
}
Err(err) => {
self.logger
.warn(&format!("Failed to verify hook cleanup: {err}"));
}
}
cleanup_generated_files_with_workspace(self.workspace);
if !try_remove_ralph_dir(repo_root) {
let remaining = verify_ralph_dir_removed(repo_root);
self.logger.warn(&format!(
"Ralph git dir still present after guard cleanup: {}",
remaining.join(", ")
));
}
crate::git_helpers::clear_agent_phase_global_state();
}
}