Finish long-running agent parity

This commit is contained in:
Georg Bauer
2026-07-26 13:41:53 +02:00
parent 65c9cbfc45
commit 171b041ba6
15 changed files with 896 additions and 324 deletions

View File

@@ -364,7 +364,7 @@ pub(crate) struct GenerationOutput {
#[cfg(target_os = "macos")]
pub(crate) struct CompactionOutput {
pub(crate) summary: String,
pub(crate) tail: Vec<ChatTurn>,
pub(crate) tail_start: usize,
pub(crate) context_tokens: u32,
pub(crate) checkpoint: PathBuf,
}
@@ -530,19 +530,23 @@ impl Generator {
Ok(output)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn compact(
&mut self,
messages: &[ChatTurn],
settings: &TurnSettings,
rebuild_system_prompt: &str,
reason: &str,
checkpoint: &Path,
cancelled: &AtomicBool,
mut progress: impl FnMut(u32, u32, Option<f32>),
mut phase: impl FnMut(&'static str),
) -> Result<CompactionOutput, String> {
let _ = std::fs::remove_file(checkpoint);
self.executor.reset()?;
self.checkpoint = None;
let result = (|| {
phase("Compacting durable task state…");
let mut private_messages = messages.to_vec();
private_messages.push(ChatTurn {
user: true,
@@ -555,15 +559,24 @@ impl Generator {
});
let mut private_settings = settings.clone();
private_settings.reasoning_mode = ReasoningMode::Direct;
private_settings.max_generated_tokens = crate::compaction::SUMMARY_MAX_TOKENS;
let private_prompt = self.executor.model().render_conversation(
&private_settings.system_prompt,
&private_messages,
private_settings.reasoning_mode,
);
private_settings.max_generated_tokens = crate::compaction::summary_budget(
private_prompt.len().min(u32::MAX as usize) as u32,
self.executor.context(),
)
.ok_or_else(|| "not enough context left to request compaction summary".to_owned())?;
private_settings.temperature = 0.0;
private_settings.stops.extend([
private_settings.stops = vec![
"<DSML".into(),
"<DSML".into(),
"<tool_call>".into(),
"<think>".into(),
"</think>".into(),
]);
];
let (output, prompt_complete) = self.generate_inner(
&private_messages,
&private_settings,
@@ -580,6 +593,7 @@ impl Generator {
}
// The private request must never become the rebuilt session prefix.
phase("Rebuilding compacted context…");
self.executor.reset()?;
self.checkpoint = None;
@@ -609,7 +623,7 @@ impl Generator {
);
let tail = messages[start..].to_vec();
let rebuilt_system =
crate::compaction::summary_system_prompt(&settings.system_prompt, Some(&summary));
crate::compaction::summary_system_prompt(rebuild_system_prompt, Some(&summary));
let history_tokens = self.executor.model().render_history(
&rebuilt_system,
&tail,
@@ -627,10 +641,11 @@ impl Generator {
return Err("context compaction interrupted during rebuild".into());
}
let tag = conversation_tag(&rebuilt_system, settings.reasoning_mode, &tail);
phase("Saving compacted context…");
self.save_checkpoint(checkpoint, tag)?;
Ok(CompactionOutput {
summary,
tail,
tail_start: start,
context_tokens: history_tokens.len() as u32,
checkpoint: checkpoint.to_owned(),
})
@@ -645,6 +660,20 @@ impl Generator {
result
}
pub(crate) fn rendered_history_tokens(
&self,
messages: &[ChatTurn],
settings: &TurnSettings,
) -> Result<u32, String> {
u32::try_from(
self.executor
.model()
.render_history(&settings.system_prompt, messages, settings.reasoning_mode)
.len(),
)
.map_err(|_| "rendered conversation is too large".to_owned())
}
fn select_checkpoint(
&mut self,
checkpoint: &Path,