bamboo_engine/runtime/execution/runner_state.rs
1//! Runner state types for background agent execution.
2//!
3//! Provides the `AgentRunner` and `AgentStatus` types that track the lifecycle
4//! of an in-progress agent execution. These are used by the execution
5//! orchestration layer across all background paths (HTTP execute, spawn, schedule).
6
7use chrono::{DateTime, Utc};
8use tokio::sync::broadcast;
9use tokio_util::sync::CancellationToken;
10
11use bamboo_agent_core::AgentEvent;
12
13/// Status of an agent execution runner.
14///
15/// Represents the lifecycle state of an agent run from initialization
16/// through completion or error.
17#[derive(Debug, Clone)]
18pub enum AgentStatus {
19 /// Agent is initialized but not yet running.
20 Pending,
21
22 /// Agent is currently executing.
23 Running,
24
25 /// Agent completed successfully.
26 Completed,
27
28 /// Agent execution was cancelled by user.
29 Cancelled,
30
31 /// Agent execution failed with an error message.
32 Error(String),
33}
34
35/// Runner that manages agent execution for a session.
36///
37/// Each active agent run has an associated `AgentRunner` that coordinates
38/// event broadcasting, cancellation, and status tracking.
39///
40/// # Event Broadcasting
41///
42/// Uses a broadcast channel to support multiple subscribers watching
43/// the same agent run simultaneously.
44///
45/// # Cancellation
46///
47/// Provides a cancellation token that can be used to gracefully stop
48/// an in-progress agent execution.
49#[derive(Debug, Clone)]
50pub struct AgentRunner {
51 /// Broadcast sender for agent events.
52 ///
53 /// Allows multiple clients to subscribe to agent events
54 /// via `event_sender.subscribe()`.
55 pub event_sender: broadcast::Sender<AgentEvent>,
56
57 /// Cancellation token for graceful shutdown.
58 ///
59 /// When triggered, the agent should stop execution at the
60 /// next safe point.
61 pub cancel_token: CancellationToken,
62
63 /// Current status of the agent run.
64 pub status: AgentStatus,
65
66 /// Timestamp when the run was started.
67 pub started_at: DateTime<Utc>,
68
69 /// Timestamp when the run completed (if finished).
70 pub completed_at: Option<DateTime<Utc>>,
71
72 /// Last token budget event to replay for new subscribers.
73 ///
74 /// When a new client subscribes to an ongoing run, this
75 /// allows them to receive the most recent token usage info.
76 pub last_budget_event: Option<AgentEvent>,
77
78 /// Name of the most recently executed tool (if any).
79 /// Updated live during execution for diagnostic visibility.
80 pub last_tool_name: Option<String>,
81
82 /// Phase of the most recently executed tool: "begin", "finished", or "error".
83 /// Updated live during execution for diagnostic visibility.
84 pub last_tool_phase: Option<String>,
85
86 /// Timestamp of the last event received during this run.
87 /// Updated live during execution for liveness checks.
88 pub last_event_at: Option<DateTime<Utc>>,
89
90 /// Number of completed rounds (turns) so far.
91 /// Updated live during execution for progress tracking.
92 pub round_count: u32,
93}
94
95impl Default for AgentRunner {
96 fn default() -> Self {
97 Self::new()
98 }
99}
100
101impl AgentRunner {
102 /// Broadcast channel capacity for agent events.
103 pub const EVENT_CHANNEL_CAPACITY: usize = 1000;
104
105 /// Create a new agent runner with default settings.
106 ///
107 /// Initializes a broadcast channel, a fresh cancellation token,
108 /// and `Pending` status.
109 pub fn new() -> Self {
110 let (event_sender, _) = broadcast::channel(Self::EVENT_CHANNEL_CAPACITY);
111 Self {
112 event_sender,
113 cancel_token: CancellationToken::new(),
114 status: AgentStatus::Pending,
115 started_at: Utc::now(),
116 completed_at: None,
117 last_budget_event: None,
118 last_tool_name: None,
119 last_tool_phase: None,
120 last_event_at: None,
121 round_count: 0,
122 }
123 }
124}