a3s_code_core/retention.rs
1//! In-memory retention limits for long-running sessions.
2//!
3//! The framework's in-memory stores
4//! ([`InMemoryRunStore`](crate::run::InMemoryRunStore),
5//! [`InMemoryTraceSink`](crate::trace::InMemoryTraceSink),
6//! [`InMemorySubagentTaskTracker`](crate::subagent_task_tracker::InMemorySubagentTaskTracker))
7//! accumulate unboundedly by default — fine for short-lived runs, a
8//! memory leak for sessions that live for hours or days under cluster
9//! workloads.
10//!
11//! `SessionRetentionLimits` lets the host cap each store with a FIFO
12//! policy. `None` for any field keeps the unbounded default, so
13//! callers that don't set anything see no behaviour change.
14//!
15//! All caps are **soft**: when a store hits its cap, the oldest entry
16//! is dropped on insert. The framework never returns errors from cap
17//! enforcement.
18
19/// Per-session in-memory retention caps. Built via
20/// [`SessionOptions::with_retention_limits`](crate::agent_api::SessionOptions::with_retention_limits)
21/// or by constructing the struct directly.
22#[derive(Debug, Clone, Copy, Default)]
23pub struct SessionRetentionLimits {
24 /// Maximum number of runs retained in
25 /// [`InMemoryRunStore`](crate::run::InMemoryRunStore).
26 ///
27 /// When a new run is created past this cap, the **oldest** run
28 /// (by insertion order) is dropped along with its events.
29 /// `None` (default) keeps all runs.
30 pub max_runs_retained: Option<usize>,
31
32 /// Maximum number of event records retained per run in
33 /// [`InMemoryRunStore`](crate::run::InMemoryRunStore).
34 ///
35 /// When a run accumulates more events than this, the oldest
36 /// events are FIFO-dropped. The run snapshot's `event_count`
37 /// is **not** decremented — it remains the total ever recorded.
38 /// `None` (default) keeps all events.
39 pub max_events_per_run: Option<usize>,
40
41 /// Maximum number of events retained in
42 /// [`InMemoryTraceSink`](crate::trace::InMemoryTraceSink).
43 ///
44 /// When the sink reaches this cap, the oldest event is dropped
45 /// on each new write. `None` (default) keeps all events.
46 pub max_trace_events: Option<usize>,
47
48 /// Maximum number of **terminal** (Completed / Failed / Cancelled)
49 /// subagent task snapshots retained in
50 /// [`InMemorySubagentTaskTracker`](crate::subagent_task_tracker::InMemorySubagentTaskTracker).
51 /// Running tasks are never dropped.
52 ///
53 /// When the count of terminal entries exceeds this cap, the
54 /// oldest terminal entry (by completion time) is dropped.
55 /// `None` (default) keeps all terminal entries.
56 pub max_terminal_subagent_tasks: Option<usize>,
57}
58
59impl SessionRetentionLimits {
60 /// Convenience builder.
61 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn with_max_runs(mut self, n: usize) -> Self {
66 self.max_runs_retained = Some(n);
67 self
68 }
69
70 pub fn with_max_events_per_run(mut self, n: usize) -> Self {
71 self.max_events_per_run = Some(n);
72 self
73 }
74
75 pub fn with_max_trace_events(mut self, n: usize) -> Self {
76 self.max_trace_events = Some(n);
77 self
78 }
79
80 pub fn with_max_terminal_subagent_tasks(mut self, n: usize) -> Self {
81 self.max_terminal_subagent_tasks = Some(n);
82 self
83 }
84}