journal: wire standalone agent into hook cycle
Add journal_cycle() to memory_search.rs, triggered every 20KB of transcript growth. Runs independently of the surface-observe pipeline so it doesn't depend on the 5-step pipeline surviving bail checks. Journal agent doesn't inject output into conversation context (unlike surface and reflect) — it just writes episodic memory entries.
This commit is contained in:
parent
43f0abeaec
commit
3a8383ba37
1 changed files with 34 additions and 0 deletions
|
|
@ -287,6 +287,39 @@ fn reflection_cycle(session: &Session, out: &mut String, log_f: &mut File) {
|
||||||
let _ = writeln!(log_f, "reflect: spawned {:?}", pid);
|
let _ = writeln!(log_f, "reflect: spawned {:?}", pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Run the journal agent on its own cadence — every 20KB of transcript.
|
||||||
|
/// Standalone agent that captures episodic memory independently of the
|
||||||
|
/// surface-observe pipeline.
|
||||||
|
fn journal_cycle(session: &Session, log_f: &mut File) {
|
||||||
|
let state_dir = crate::store::memory_dir()
|
||||||
|
.join("agent-output")
|
||||||
|
.join("journal");
|
||||||
|
fs::create_dir_all(&state_dir).ok();
|
||||||
|
|
||||||
|
let offset_path = state_dir.join("transcript-offset");
|
||||||
|
let transcript = session.transcript();
|
||||||
|
|
||||||
|
let last_offset: u64 = fs::read_to_string(&offset_path).ok()
|
||||||
|
.and_then(|s| s.trim().parse().ok())
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
const JOURNAL_INTERVAL: u64 = 20_000;
|
||||||
|
if transcript.size.saturating_sub(last_offset) < JOURNAL_INTERVAL {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let live = crate::agents::knowledge::scan_pid_files(&state_dir, 300);
|
||||||
|
if !live.is_empty() {
|
||||||
|
let _ = writeln!(log_f, "journal: already running {:?}", live);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::write(&offset_path, transcript.size.to_string()).ok();
|
||||||
|
let pid = crate::agents::knowledge::spawn_agent(
|
||||||
|
"journal", &state_dir, &session.session_id);
|
||||||
|
let _ = writeln!(log_f, "journal: spawned {:?}", pid);
|
||||||
|
}
|
||||||
|
|
||||||
fn cleanup_stale_files(dir: &Path, max_age: Duration) {
|
fn cleanup_stale_files(dir: &Path, max_age: Duration) {
|
||||||
let entries = match fs::read_dir(dir) {
|
let entries = match fs::read_dir(dir) {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
|
|
@ -367,6 +400,7 @@ fn hook(session: &Session) -> String {
|
||||||
if cfg.surface_hooks.iter().any(|h| h == &session.hook_event) {
|
if cfg.surface_hooks.iter().any(|h| h == &session.hook_event) {
|
||||||
surface_observe_cycle(session, &mut out, &mut log_f);
|
surface_observe_cycle(session, &mut out, &mut log_f);
|
||||||
reflection_cycle(session, &mut out, &mut log_f);
|
reflection_cycle(session, &mut out, &mut log_f);
|
||||||
|
journal_cycle(session, &mut log_f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue