webterm_agent/models/
pty_activity.rs

1use crate::models::agent_error::AgentError;
2use crate::models::pty_activity_reader::PtyActivityReader;
3use pty_process::{Command, OwnedWritePty, Pty, Size};
4use tokio::io::AsyncWriteExt;
5use tokio::sync::Mutex;
6use webterm_core::types::ActivityId;
7
8pub struct PtyActivity {
9    // required to keep the reader alive
10    _pty_reader: PtyActivityReader,
11    pty_writer: Mutex<OwnedWritePty>,
12}
13
14impl PtyActivity {
15    pub async fn new(activity_id: ActivityId, command: &str) -> Result<Self, AgentError> {
16        let pty = Pty::new()?;
17        let mut command = Command::new(command);
18        command.env("TERM", "xterm-256color");
19        command.spawn(&pty.pts().unwrap())?;
20        let (pty_reader, pty_writer) = pty.into_split();
21        let pty_writer = Mutex::new(pty_writer);
22        Ok(PtyActivity {
23            pty_writer,
24            _pty_reader: PtyActivityReader::new(activity_id, pty_reader),
25        })
26    }
27
28    pub async fn resize(&self, cols: u16, rows: u16) -> Result<(), AgentError> {
29        self.pty_writer.lock().await.resize(Size::new(cols, rows))?;
30        Ok(())
31    }
32
33    pub async fn write(&self, data: &[u8]) -> Result<(), AgentError> {
34        self.pty_writer.lock().await.write_all(data).await?;
35        Ok(())
36    }
37
38    pub async fn shutdown(&self) -> Result<(), AgentError> {
39        self.pty_writer.lock().await.shutdown().await?;
40        Ok(())
41    }
42}