use anyhow::Result;
use owo_colors::OwoColorize;
use std::sync::Arc;
use crate::pty::PtyManager;
use super::super::interactive_signal::{
TerminalGuard, reset_interrupt, setup_async_signal_handlers, setup_signal_handlers,
};
use super::types::{InteractiveCommand, InteractiveResult};
impl InteractiveCommand {
pub async fn execute(self) -> Result<InteractiveResult> {
let use_pty = self.should_use_pty()?;
if use_pty {
self.execute_with_pty().await
} else {
self.execute_traditional().await
}
}
pub(super) async fn execute_with_pty(self) -> Result<InteractiveResult> {
let start_time = std::time::Instant::now();
println!("Starting interactive session with PTY support...");
let nodes_to_connect = self.select_nodes_to_connect()?;
let mut channels = Vec::new();
let mut connected_nodes = Vec::new();
for node in nodes_to_connect {
match self.connect_to_node_pty(node.clone()).await {
Ok(channel) => {
println!("✓ Connected to {} with PTY", node.to_string().green());
channels.push(channel);
connected_nodes.push(node);
}
Err(e) => {
eprintln!("✗ Failed to connect to {}: {}", node.to_string().red(), e);
}
}
}
if channels.is_empty() {
anyhow::bail!("Failed to connect to any nodes");
}
let nodes_connected = channels.len();
let mut pty_manager = PtyManager::new();
if self.single_node && channels.len() == 1 {
let session_id = pty_manager
.create_single_session(
channels.into_iter().next().unwrap(),
self.pty_config.clone(),
)
.await?;
pty_manager.run_single_session(session_id).await?;
} else {
let session_ids = pty_manager
.create_multiplex_sessions(channels, self.pty_config.clone())
.await?;
pty_manager.run_multiplex_sessions(session_ids).await?;
}
crate::pty::terminal::force_terminal_cleanup();
let _ = std::io::Write::flush(&mut std::io::stdout());
Ok(InteractiveResult {
duration: start_time.elapsed(),
commands_executed: 0, nodes_connected,
})
}
pub(super) async fn execute_traditional(self) -> Result<InteractiveResult> {
let start_time = std::time::Instant::now();
let _terminal_guard = TerminalGuard::new();
let shutdown = setup_signal_handlers()?;
setup_async_signal_handlers(Arc::clone(&shutdown)).await;
reset_interrupt();
let nodes_to_connect = self.select_nodes_to_connect()?;
println!("Connecting to {} node(s)...", nodes_to_connect.len());
let mut sessions = Vec::new();
for node in nodes_to_connect {
match self.connect_to_node(node.clone()).await {
Ok(session) => {
println!("✓ Connected to {}", session.node.to_string().green());
sessions.push(session);
}
Err(e) => {
eprintln!("✗ Failed to connect to {}: {}", node.to_string().red(), e);
}
}
}
if sessions.is_empty() {
anyhow::bail!("Failed to connect to any nodes");
}
let nodes_connected = sessions.len();
let commands_executed = if self.single_node {
self.run_single_node_mode(sessions.into_iter().next().unwrap())
.await?
} else {
self.run_multiplex_mode(sessions).await?
};
Ok(InteractiveResult {
duration: start_time.elapsed(),
commands_executed,
nodes_connected,
})
}
}