use std::sync::Arc;
use atomr_agents_coding_cli_core::{
CliCommand, CliRequest, CliSessionId, CliVendor,
};
use atomr_agents_coding_cli_isolator::{IsolationOpts, Isolator};
use crate::error::{HarnessError, Result};
use crate::pty_pump;
use crate::session::InteractiveSessionHandle;
const TMUX_BIN: &str = "tmux";
pub(crate) async fn start_session(
id: CliSessionId,
vendor: Arc<dyn CliVendor>,
isolator: Arc<dyn Isolator>,
req: CliRequest,
) -> Result<Arc<InteractiveSessionHandle>> {
vendor.materialize_config(&req.project, &req.workdir).await?;
let inner = vendor.build_interactive_command(&req, &req.workdir);
let tmux_session = format!("atomr-cli-{}", id.as_str());
let mut create = CliCommand::new(TMUX_BIN, req.workdir.clone())
.arg("new-session")
.arg("-d")
.arg_pair("-s", tmux_session.clone())
.arg_pair("-c", req.workdir.to_string_lossy().into_owned());
create = create.arg(inner.program.as_os_str());
for a in &inner.args {
create = create.arg(a);
}
for (k, v) in &inner.env {
create = create.envv(k, v);
}
let mut create_handle = isolator
.spawn(
create,
IsolationOpts {
capture_stdout: false,
capture_stderr: true,
grace: None,
},
)
.await?;
let create_status = create_handle.wait().await?;
if !create_status.success {
return Err(HarnessError::InvalidRequest(format!(
"tmux new-session failed with exit code {:?}; check that tmux is installed in the isolator",
create_status.code
)));
}
let attach = CliCommand::new(TMUX_BIN, req.workdir.clone())
.arg("attach-session")
.arg_pair("-t", tmux_session.clone())
.with_pty();
let attach_handle = isolator.spawn(attach, IsolationOpts::default()).await?;
let pumps = pty_pump::spawn(attach_handle);
let handle = InteractiveSessionHandle {
id: id.clone(),
vendor: vendor.kind(),
tmux_session,
started_at: chrono::Utc::now(),
request: req,
events: pumps.events_tx,
input: pumps.input_tx,
closed: pumps.closed,
};
Ok(Arc::new(handle))
}
pub(crate) async fn stop_session(
isolator: Arc<dyn Isolator>,
tmux_session: &str,
workdir: std::path::PathBuf,
) -> Result<()> {
let cmd = CliCommand::new(TMUX_BIN, workdir)
.arg("kill-session")
.arg_pair("-t", tmux_session);
let mut h = isolator
.spawn(
cmd,
IsolationOpts {
capture_stdout: false,
capture_stderr: false,
grace: None,
},
)
.await?;
let _ = h.wait().await;
Ok(())
}