Skip to main content

vtcode_core/tools/registry/
pty_facade.rs

1//! PTY-related ToolRegistry accessors.
2
3use std::future::Future;
4use std::sync::Arc;
5
6use anyhow::Result;
7
8use crate::config::PtyConfig;
9use crate::tools::exec_session::ExecSessionManager;
10use crate::tools::pty::PtyManager;
11
12use super::ToolRegistry;
13use super::pty;
14
15impl ToolRegistry {
16    pub fn pty_manager(&self) -> &PtyManager {
17        self.pty_sessions.manager()
18    }
19
20    pub fn pty_config(&self) -> &PtyConfig {
21        self.pty_sessions.config()
22    }
23
24    pub fn can_start_pty_session(&self) -> bool {
25        self.pty_sessions.can_start_session()
26    }
27
28    pub fn start_pty_session(&self) -> Result<pty::PtySessionGuard> {
29        self.pty_sessions.start_session()
30    }
31
32    pub fn end_pty_session(&self) {
33        self.pty_sessions.end_session();
34    }
35
36    pub fn active_pty_sessions(&self) -> usize {
37        self.pty_sessions.active_sessions()
38    }
39
40    pub fn terminate_all_pty_sessions(&self) {
41        self.pty_sessions.terminate_all();
42    }
43
44    /// Inline-delegating wrapper over [`pty::PtySessionManager::terminate_all_async`].
45    /// Returns the inner future directly to avoid an extra coroutine state machine
46    /// (per the async-state-machine bloat audit, section 16).
47    pub fn terminate_all_pty_sessions_async(&self) -> impl Future<Output = Result<()>> + '_ {
48        self.pty_sessions.terminate_all_async()
49    }
50
51    /// Inline-delegating wrapper over
52    /// [`Self::terminate_all_exec_sessions_async`].
53    pub fn terminate_all_exec_sessions_async(&self) -> impl Future<Output = Result<()>> + '_ {
54        self.exec_sessions.terminate_all_sessions_async()
55    }
56
57    /// Exit-path variant: terminates every exec session with `Immediate` PTY
58    /// semantics (group SIGKILL, no SIGTERM grace window) so user-initiated
59    /// exit is not parked ~600 ms per live PTY session.
60    pub fn terminate_all_exec_sessions_for_exit_async(&self) -> impl Future<Output = Result<()>> + '_ {
61        self.exec_sessions.terminate_all_sessions_for_exit_async()
62    }
63
64    /// Inline-delegating wrapper that terminates only foreground exec sessions
65    /// after a turn interruption, preserving user-owned background sessions.
66    pub fn terminate_active_exec_sessions_async(&self) -> impl Future<Output = Result<()>> + '_ {
67        self.exec_sessions.terminate_active_sessions_async()
68    }
69
70    /// Exit-path variant of [`Self::terminate_active_exec_sessions_async`]
71    /// using `Immediate` PTY termination.
72    pub fn terminate_active_exec_sessions_for_exit_async(&self) -> impl Future<Output = Result<()>> + '_ {
73        self.exec_sessions.terminate_active_sessions_for_exit_async()
74    }
75
76    pub fn exec_session_manager(&self) -> ExecSessionManager {
77        self.exec_sessions.clone()
78    }
79
80    /// Set the active PTY sessions counter for tracking
81    pub fn set_active_pty_sessions(&self, counter: Arc<std::sync::atomic::AtomicUsize>) {
82        self.exec_sessions.set_foreground_pty_counter(Arc::clone(&counter));
83        if let Ok(mut guard) = self.active_pty_sessions.write() {
84            *guard = Some(counter);
85        }
86    }
87
88    /// Increment active PTY sessions count
89    pub fn increment_active_pty_sessions(&self) {
90        if let Some(counter) = self
91            .active_pty_sessions
92            .read()
93            .unwrap_or_else(|e| e.into_inner())
94            .as_ref()
95            .map(Arc::clone)
96        {
97            counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
98        }
99    }
100
101    /// Decrement active PTY sessions count
102    pub fn decrement_active_pty_sessions(&self) {
103        if let Some(counter) = self
104            .active_pty_sessions
105            .read()
106            .unwrap_or_else(|e| e.into_inner())
107            .as_ref()
108            .map(Arc::clone)
109        {
110            counter.fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
111        }
112    }
113
114    /// Get the current active PTY sessions count
115    pub fn active_pty_sessions_count(&self) -> usize {
116        self.active_pty_sessions
117            .read()
118            .ok()
119            .and_then(|g| g.as_ref().map(|c| c.load(std::sync::atomic::Ordering::Relaxed)))
120            .unwrap_or(0)
121    }
122}