remowt-client 0.1.1

russh-based client connection to a remowt agent
Documentation
use anyhow::{anyhow, Result};
use bifrostlink::declarative::RemoteEndpoints as _;
use bifrostlink::Remote;
use remowt_endpoints::pty::{PtyClient, ShellId};
use remowt_link_shared::{Address, BifConfig};
use uuid::Uuid;

use crate::forwarded::RemowtStream;
use crate::Remowt;

pub struct RemowtShell {
	pub id: ShellId,
	pub stream: RemowtStream,
	remote: Remote<BifConfig>,
}
impl RemowtShell {
	pub fn resizer(&self) -> RemowtShellResizer {
		RemowtShellResizer {
			remote: self.remote.clone(),
			id: self.id,
		}
	}
}

#[derive(Clone)]
pub struct RemowtShellResizer {
	remote: Remote<BifConfig>,
	id: ShellId,
}

impl RemowtShellResizer {
	pub async fn resize(&self, cols: u16, rows: u16) -> Result<()> {
		PtyClient::wrap(self.remote.clone())
			.resize(self.id, cols, rows)
			.await?
			.map_err(|e| anyhow!("failed to resize remote shell: {e}"))
	}
}

impl Remowt {
	pub async fn open_shell(&self, term: &str, cols: u16, rows: u16) -> Result<RemowtShell> {
		let sock = self
			.runtime_dir()
			.join(format!("remowt-shell-{}.sock", Uuid::new_v4()));

		let forwarded = self.forward_socket(&sock).await?;
		let client: PtyClient<BifConfig> = self.endpoints();
		let id = client
			.open_shell(sock, term.to_owned(), cols, rows)
			.await?
			.map_err(|e| anyhow!("agent failed to open shell: {e}"))?;
		let stream = forwarded.accept().await?;

		Ok(RemowtShell {
			id,
			stream,
			remote: self.rpc.remote(Address::Agent),
		})
	}
}