From 41b3f50c917dd9cb1fb63376fb626e2a764f22b1 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 2 Apr 2026 23:06:08 -0400 Subject: [PATCH] keep 2 most recent images, age out the rest age_out_images now keeps 1 existing image + 1 about to be added = 2 live images for motion/comparison. Previously aged all to 1. Reduces image bloat in conversation log and context. Co-Authored-By: Proof of Concept --- src/agent/runner.rs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/agent/runner.rs b/src/agent/runner.rs index 6312bac..d9cece5 100644 --- a/src/agent/runner.rs +++ b/src/agent/runner.rs @@ -897,33 +897,34 @@ impl Agent { } /// Replace base64 image data in older messages with text placeholders. - /// Only the most recent image stays live — each new image ages out - /// all previous ones. The tool result message (right before each image - /// message) already records what was loaded, so no info is lost. + /// Keeps the 2 most recent images live (enough for motion/comparison). + /// The tool result message before each image records what was loaded. fn age_out_images(&mut self) { - for entry in &mut self.context.entries { - let msg = entry.message_mut(); + // Find image entries newest-first, skip 1 (caller is about to add another) + let to_age: Vec = self.context.entries.iter().enumerate() + .rev() + .filter(|(_, e)| { + if let Some(MessageContent::Parts(parts)) = &e.message().content { + parts.iter().any(|p| matches!(p, ContentPart::ImageUrl { .. })) + } else { false } + }) + .map(|(i, _)| i) + .skip(1) // keep 1 existing + 1 about to be added = 2 live + .collect(); + + for i in to_age { + let msg = self.context.entries[i].message_mut(); if let Some(MessageContent::Parts(parts)) = &msg.content { - let has_images = parts.iter().any(|p| matches!(p, ContentPart::ImageUrl { .. })); - if !has_images { - continue; - } let mut replacement = String::new(); for part in parts { match part { ContentPart::Text { text } => { - if !replacement.is_empty() { - replacement.push('\n'); - } + if !replacement.is_empty() { replacement.push('\n'); } replacement.push_str(text); } ContentPart::ImageUrl { .. } => { - if !replacement.is_empty() { - replacement.push('\n'); - } - replacement.push_str( - "[image aged out — see tool result above for details]", - ); + if !replacement.is_empty() { replacement.push('\n'); } + replacement.push_str("[image aged out]"); } } }