use anyhow::{Context, Result};
use std::path::Path;
use std::thread;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use crate::callback;
pub fn run(
file: &Path,
timeout_secs: u64,
poll_interval_ms: u64,
fallback_model: &str,
) -> Result<()> {
eprintln!("[cleanup] writing callback request for {}", file.display());
let _request = callback::create_request(
file,
&["compact", "prune-pending", "summary"],
None,
timeout_secs + 10, )?;
eprintln!("[cleanup] polling for response (timeout: {}s, interval: {}ms)",
timeout_secs, poll_interval_ms);
let deadline = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
+ timeout_secs;
let mut response = None;
while SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
< deadline
{
thread::sleep(Duration::from_millis(poll_interval_ms));
if let Some(resp) = callback::read_response(file)? {
response = Some(resp);
break;
}
}
let summary = if let Some(resp) = response {
callback::delete_response(file)?;
eprintln!("[cleanup] received callback response from Claude session");
eprintln!("[cleanup] {}", resp.summary);
resp.summary.clone()
} else {
eprintln!("[cleanup] no response from session, spawning fallback agent");
spawn_fallback_agent(file, fallback_model)?
};
eprintln!("[cleanup] done: {}", summary);
Ok(())
}
fn spawn_fallback_agent(file: &Path, model: &str) -> Result<String> {
eprintln!("[cleanup] spawning fallback agent: claude --print --model {}", model);
let content = std::fs::read_to_string(file)
.context("could not read document for fallback summarization")?;
let max_chars = 30_000;
let truncated = if content.len() > max_chars {
&content[..max_chars]
} else {
&content
};
let prompt = format!(
"Summarize the following document exchange into a concise paragraph. \
Focus on decisions made, work completed, and open items. \
Output ONLY the summary text, nothing else.\n\n---\n\n{}",
truncated
);
let output = std::process::Command::new("claude")
.args(["--print", "--model", model, "-p"])
.arg(&prompt)
.output()
.context("failed to spawn claude --print for fallback summarization")?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
anyhow::bail!("claude --print failed: {}", stderr);
}
let summary = String::from_utf8_lossy(&output.stdout).trim().to_string();
Ok(summary)
}