seen_recent: cap at 20 roots total across both seen sets
Budget of 20 roots split between current and prev. Current gets priority, prev fills the remainder. Prevents flooding the agent with hundreds of previously surfaced keys. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9512dc0a31
commit
53b63ab45b
1 changed files with 25 additions and 17 deletions
|
|
@ -520,34 +520,42 @@ fn resolve_seen_recent() -> String {
|
||||||
|
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
|
|
||||||
|
const MAX_ROOTS: usize = 20;
|
||||||
|
|
||||||
// Current: already in this context, don't re-surface
|
// Current: already in this context, don't re-surface
|
||||||
if !current.is_empty() {
|
// Sort newest first, dedup, cap
|
||||||
|
let mut current_sorted = current.clone();
|
||||||
|
current_sorted.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
let mut seen_keys = std::collections::HashSet::new();
|
||||||
|
let current_deduped: Vec<_> = current_sorted.into_iter()
|
||||||
|
.filter(|(_, key)| seen_keys.insert(key.clone()))
|
||||||
|
.take(MAX_ROOTS)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !current_deduped.is_empty() {
|
||||||
out.push_str("Already surfaced this context (don't re-surface unless conversation shifted):\n");
|
out.push_str("Already surfaced this context (don't re-surface unless conversation shifted):\n");
|
||||||
let mut seen = std::collections::HashSet::new();
|
for (ts, key) in ¤t_deduped {
|
||||||
for (ts, key) in ¤t {
|
|
||||||
if seen.insert(key.clone()) {
|
|
||||||
out.push_str(&format!("- {} (surfaced {})\n", key, ts));
|
out.push_str(&format!("- {} (surfaced {})\n", key, ts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Prev: surfaced before compaction, MAY need re-surfacing
|
// Prev: surfaced before compaction, MAY need re-surfacing
|
||||||
if !prev.is_empty() {
|
// Exclude anything already in current, sort newest first, cap at remaining budget
|
||||||
let current_keys: std::collections::HashSet<_> = current.iter()
|
let remaining = MAX_ROOTS.saturating_sub(current_deduped.len());
|
||||||
.map(|(_, k)| k.as_str()).collect();
|
if remaining > 0 && !prev.is_empty() {
|
||||||
let prev_only: Vec<_> = prev.iter()
|
let mut prev_sorted = prev.clone();
|
||||||
.filter(|(_, k)| !current_keys.contains(k.as_str()))
|
prev_sorted.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
let prev_deduped: Vec<_> = prev_sorted.into_iter()
|
||||||
|
.filter(|(_, key)| seen_keys.insert(key.clone()))
|
||||||
|
.take(remaining)
|
||||||
.collect();
|
.collect();
|
||||||
if !prev_only.is_empty() {
|
if !prev_deduped.is_empty() {
|
||||||
out.push_str("\nSurfaced before compaction (context was reset — re-surface if still relevant):\n");
|
out.push_str("\nSurfaced before compaction (context was reset — re-surface if still relevant):\n");
|
||||||
let mut seen = std::collections::HashSet::new();
|
for (ts, key) in &prev_deduped {
|
||||||
for (ts, key) in prev_only {
|
|
||||||
if seen.insert(key.clone()) {
|
|
||||||
out.push_str(&format!("- {} (pre-compaction, {})\n", key, ts));
|
out.push_str(&format!("- {} (pre-compaction, {})\n", key, ts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
out.trim_end().to_string()
|
out.trim_end().to_string()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue