surface agent infrastructure: hook spawn, seen set rotation, config
Surface agent fires asynchronously on UserPromptSubmit, deposits results for the next prompt to consume. This commit adds: - poc-hook: spawn surface agent with PID tracking and configurable timeout, consume results (NEW RELEVANT MEMORIES / NO NEW), render and inject surfaced memories, observation trigger on conversation volume - memory-search: rotate seen set on compaction (current → prev) instead of deleting, merge both for navigation roots - config: surface_timeout_secs option The .agent file and agent output routing are still pending. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
53c5424c98
commit
85307fd6cb
3 changed files with 170 additions and 2 deletions
|
|
@ -110,10 +110,16 @@ fn main() {
|
|||
let is_first = !cookie_path.exists();
|
||||
|
||||
if is_first || is_compaction {
|
||||
// Reset seen set and returned list
|
||||
// Rotate seen set: current → prev (for surface agent navigation roots)
|
||||
let seen_path = state_dir.join(format!("seen-{}", session_id));
|
||||
let seen_prev_path = state_dir.join(format!("seen-prev-{}", session_id));
|
||||
let returned_path = state_dir.join(format!("returned-{}", session_id));
|
||||
fs::remove_file(&seen_path).ok();
|
||||
if is_compaction {
|
||||
fs::rename(&seen_path, &seen_prev_path).ok();
|
||||
} else {
|
||||
fs::remove_file(&seen_path).ok();
|
||||
fs::remove_file(&seen_prev_path).ok();
|
||||
}
|
||||
fs::remove_file(&returned_path).ok();
|
||||
}
|
||||
|
||||
|
|
@ -592,6 +598,35 @@ fn parse_seen_line(line: &str) -> &str {
|
|||
line.split_once('\t').map(|(_, key)| key).unwrap_or(line)
|
||||
}
|
||||
|
||||
/// Load the most recently surfaced memory keys, sorted newest-first, capped at `limit`.
|
||||
/// Used to give the surface agent navigation roots.
|
||||
fn load_recent_seen(dir: &Path, session_id: &str, limit: usize) -> Vec<String> {
|
||||
// Merge current and previous seen sets
|
||||
let mut entries: Vec<(String, String)> = Vec::new();
|
||||
for suffix in ["", "-prev"] {
|
||||
let path = dir.join(format!("seen{}-{}", suffix, session_id));
|
||||
if let Ok(content) = fs::read_to_string(&path) {
|
||||
entries.extend(
|
||||
content.lines()
|
||||
.filter(|s| !s.is_empty())
|
||||
.filter_map(|line| {
|
||||
let (ts, key) = line.split_once('\t')?;
|
||||
Some((ts.to_string(), key.to_string()))
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by timestamp descending (newest first), dedup by key
|
||||
entries.sort_by(|a, b| b.0.cmp(&a.0));
|
||||
let mut seen = HashSet::new();
|
||||
entries.into_iter()
|
||||
.filter(|(_, key)| seen.insert(key.clone()))
|
||||
.take(limit)
|
||||
.map(|(_, key)| key)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn load_seen(dir: &Path, session_id: &str) -> HashSet<String> {
|
||||
let path = dir.join(format!("seen-{}", session_id));
|
||||
if path.exists() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue