Skip to main content

agent_engine/session/
budgets.rs

1//! Teardown budgets shared by every session host (values copied from
2//! `agent-tui/src/tui/signals.rs`; `signals.rs` re-exports these on day 2).
3//!
4//! - `SAVE_TIMEOUT_SECS`  — session save + index end record (data safety first)
5//! - `HOOKS_TIMEOUT_SECS` — `on_session_end` hook emit (concurrent, fail-open)
6//! - `TEARDOWN_TIMEOUT_SECS` = their sum.
7
8pub const SAVE_TIMEOUT_SECS: u64 = 2;
9pub const HOOKS_TIMEOUT_SECS: u64 = 5;
10pub const TEARDOWN_TIMEOUT_SECS: u64 = SAVE_TIMEOUT_SECS + HOOKS_TIMEOUT_SECS;
11
12pub const SAVE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(SAVE_TIMEOUT_SECS);
13pub const HOOKS_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(HOOKS_TIMEOUT_SECS);
14
15/// `SessionActor::cancel_turn`: how long a cancelled turn's stream is drained
16/// for the engine's cancel-path history, final Usage and any in-flight
17/// context-head checkpoint. The engine's provider/tool awaits are
18/// cancellation-first, so the tail normally arrives in milliseconds; on
19/// expiry the actor keeps its last adopted (valid) history. Also the grace a
20/// driver-revoked turn gets (`revoked_turn_deadline`).
21///
22/// One exception, deliberately unbounded: a context-head checkpoint the
23/// engine hands over while draining is persisted durably before its receipt
24/// is answered (a durability barrier; dropping it would latch the session).
25pub const CANCEL_DRAIN_TIMEOUT_MS: u64 = 1_000;
26pub const CANCEL_DRAIN_TIMEOUT: std::time::Duration =
27    std::time::Duration::from_millis(CANCEL_DRAIN_TIMEOUT_MS);
28/// Whole-second ceiling of the drain, for the budget sums below/elsewhere.
29pub const CANCEL_DRAIN_TIMEOUT_SECS: u64 = CANCEL_DRAIN_TIMEOUT_MS.div_ceil(1000);
30/// Worst case of `cancel_turn`: the drain, then the bounded wait for the
31/// interrupted turn's save before it announces `Idle` (`announce_idle`).
32pub const CANCEL_TURN_TIMEOUT_SECS: u64 = CANCEL_DRAIN_TIMEOUT_SECS + SAVE_TIMEOUT_SECS;
33
34/// Session end's bounded observability flush (`finish` STEP 3).
35pub const OBSERVABILITY_FLUSH_TIMEOUT_SECS: u64 =
36    crate::runtime::telemetry::DEFAULT_SHUTDOWN_FLUSH_TIMEOUT.as_secs();
37
38/// Worst case of `SessionActor::finish`: cancel a running turn, one bounded
39/// save, the `on_session_end` hooks, the observability flush.
40pub const SESSION_END_TIMEOUT_SECS: u64 = CANCEL_TURN_TIMEOUT_SECS
41    + SAVE_TIMEOUT_SECS
42    + HOOKS_TIMEOUT_SECS
43    + OBSERVABILITY_FLUSH_TIMEOUT_SECS;
44
45/// `SessionActor::create` bound on `EngineHost::extensions_ready()`: the
46/// loader guard should make this unreachable; it exists so a session can
47/// never hang on a loader that never reports (warns, then proceeds).
48pub const EXTENSIONS_READY_TIMEOUT_SECS: u64 = 30;
49pub const EXTENSIONS_READY_TIMEOUT: std::time::Duration =
50    std::time::Duration::from_secs(EXTENSIONS_READY_TIMEOUT_SECS);
51
52/// `SessionActor::unpark` bound (B3): journal load + runtime rebuild.
53/// Transports wait `ATTACH_TIMEOUT_PARKED` (25 s) for a parked attach.
54pub const UNPARK_TIMEOUT_SECS: u64 = 20;
55pub const UNPARK_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(UNPARK_TIMEOUT_SECS);