Skip to main content

a3s_code_core/agent_api/
run_facade.rs

1use super::*;
2
3impl AgentSession {
4    /// Submit a user direction to the active run. The request is applied by
5    /// the execution loop at its next safe point and never starts a second
6    /// conversation operation.
7    pub async fn steer(
8        &self,
9        request: crate::run_control::SteerRequest,
10    ) -> crate::error::Result<crate::run_control::RunControlReceipt> {
11        if self.is_closed() {
12            return Err(crate::error::CodeError::SessionClosed {
13                session_id: self.session_id.clone(),
14            });
15        }
16        RunControl::from_session(self).steer(request).await
17    }
18
19    /// Cooperatively interrupt the active run. Cleanup, checkpoint and
20    /// single-flight settlement still happen through the normal lifecycle.
21    pub async fn interrupt(
22        &self,
23        request: crate::run_control::InterruptRequest,
24    ) -> crate::error::Result<crate::run_control::RunControlReceipt> {
25        if self.is_closed() {
26            return Err(crate::error::CodeError::SessionClosed {
27                session_id: self.session_id.clone(),
28            });
29        }
30        RunControl::from_session(self).interrupt(request).await
31    }
32
33    /// Return the optimistic-concurrency state of the active run's control
34    /// inbox, if a run is currently executing.
35    pub async fn run_control_snapshot(&self) -> Option<crate::run_control::RunControlSnapshot> {
36        RunControl::from_session(self).run_control_snapshot().await
37    }
38
39    /// Cancel a specific run only if it is still the active run.
40    ///
41    /// This is useful for SDK callers that hold a previously observed run ID:
42    /// stale run IDs will not cancel a newer operation.
43    pub async fn cancel_run(&self, run_id: &str) -> bool {
44        RunControl::from_session(self).cancel_run(run_id).await
45    }
46
47    /// Return snapshots for runs recorded by this session.
48    pub async fn runs(&self) -> Vec<crate::run::RunSnapshot> {
49        RunControl::from_session(self).runs().await
50    }
51
52    /// Return a snapshot for a recorded run.
53    pub async fn run_snapshot(&self, run_id: &str) -> Option<crate::run::RunSnapshot> {
54        RunControl::from_session(self).run_snapshot(run_id).await
55    }
56
57    /// Return recorded runtime events for a run.
58    pub async fn run_events(&self, run_id: &str) -> Vec<crate::run::RunEventRecord> {
59        RunControl::from_session(self).run_events(run_id).await
60    }
61
62    /// Return a cursor-based page from the run's retained event window.
63    ///
64    /// `after_sequence` is exclusive. The result is `None` for an unknown run;
65    /// a known run with no retained events returns an empty page. Inspect
66    /// `retention_gap` before treating the page as complete history.
67    pub async fn run_event_page(
68        &self,
69        run_id: &str,
70        after_sequence: Option<usize>,
71        limit: usize,
72    ) -> Option<crate::run::RunEventPage> {
73        RunControl::from_session(self)
74            .run_event_page(run_id, after_sequence, limit)
75            .await
76    }
77
78    /// Return one internally consistent snapshot and event page generation.
79    pub(crate) async fn run_event_observation(
80        &self,
81        run_id: &str,
82        after_sequence: Option<usize>,
83        limit: usize,
84    ) -> Option<crate::run::RunEventObservation> {
85        RunControl::from_session(self)
86            .run_event_observation(run_id, after_sequence, limit)
87            .await
88    }
89
90    /// Return a handle for the currently running operation, if any.
91    pub async fn current_run(&self) -> Option<crate::run::RunHandle> {
92        RunControl::from_session(self).current_run().await
93    }
94
95    /// Return active tool calls observed for the currently running operation.
96    pub async fn active_tools(&self) -> Vec<crate::run::ActiveToolSnapshot> {
97        SessionView::from_session(self).active_tools().await
98    }
99
100    /// Look up a delegated subagent task by id. Returns `None` if no such task
101    /// has been observed in this session.
102    pub async fn subagent_task(
103        &self,
104        task_id: &str,
105    ) -> Option<crate::subagent_task_tracker::SubagentTaskSnapshot> {
106        self.subagent_tasks.get(task_id).await
107    }
108
109    /// Return snapshots of every delegated subagent task observed in this
110    /// session (including completed and failed ones), oldest first.
111    pub async fn subagent_tasks(&self) -> Vec<crate::subagent_task_tracker::SubagentTaskSnapshot> {
112        self.subagent_tasks.list_for_parent(&self.session_id).await
113    }
114
115    /// Return snapshots of subagent tasks still in `Running` state.
116    pub async fn pending_subagent_tasks(
117        &self,
118    ) -> Vec<crate::subagent_task_tracker::SubagentTaskSnapshot> {
119        use crate::subagent_task_tracker::SubagentStatus;
120        self.subagent_tasks
121            .list_for_parent(&self.session_id)
122            .await
123            .into_iter()
124            .filter(|task| task.status == SubagentStatus::Running)
125            .collect()
126    }
127
128    /// Cancel an in-flight delegated subagent task by id. Returns `true`
129    /// when a cancellation token was found and fired, `false` when the
130    /// task id is unknown or the task has already finished. The eventual
131    /// `SubagentEnd` from the cancelled child loop won't downgrade the
132    /// terminal status — it stays `Cancelled`.
133    pub async fn cancel_subagent_task(&self, task_id: &str) -> bool {
134        self.subagent_tasks.cancel(task_id).await
135    }
136
137    /// Return a shared handle to the session's subagent task tracker.
138    ///
139    /// Advanced: embedders implementing a custom subagent execution path
140    /// (i.e. spawning child loops outside the built-in `task` tool) can use
141    /// this to register cancellation tokens and feed `AgentEvent`s into the
142    /// tracker so the standard
143    /// [`subagent_task`](Self::subagent_task) / [`pending_subagent_tasks`](Self::pending_subagent_tasks) /
144    /// [`cancel_subagent_task`](Self::cancel_subagent_task) APIs and
145    /// [`close`](Self::close) keep working uniformly across execution paths.
146    pub fn subagent_tracker(
147        &self,
148    ) -> Arc<crate::subagent_task_tracker::InMemorySubagentTaskTracker> {
149        Arc::clone(&self.subagent_tasks)
150    }
151}