Skip to main content

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}