use std::future::Future;
use std::pin::Pin;
use futures_util::Stream;
use crate::audit::{AuditLogEntry, AuditLogResponse, GetLogOptions};
use crate::client::Client;
use crate::desktop::DesktopStream;
use crate::error::BoxxkiteError;
use crate::files::{
ExecOptions, ExecResult, FileCreateResult, FileOptions, GlobOptions, GlobResult, GrepOptions,
GrepResult, HttpRequestOptions, HttpRequestResult, LsOptions, LsResult, StrReplaceOptions,
StrReplaceResult, ViewOptions, ViewResult,
};
use crate::lsp::{LspCompletionResult, LspOpenResult, LspStartResult, LspStopResult};
use crate::preview::{PreviewRevokeResult, PreviewUrl};
use crate::processes::{
ProcessInputResult, ProcessListResult, ProcessOutputResult, ProcessStartResult,
ProcessStopResult, StartProcessOptions,
};
use crate::sandboxes::CreateSandboxOptions;
use crate::takeover::TakeoverStream;
#[derive(Clone, Debug)]
pub struct SandboxSession {
client: Client,
id: String,
}
impl SandboxSession {
pub fn id(&self) -> &str {
&self.id
}
pub fn client(&self) -> &Client {
&self.client
}
pub async fn exec(
&self,
command: &str,
options: ExecOptions,
) -> Result<ExecResult, BoxxkiteError> {
self.client.exec(&self.id, command, options).await
}
pub async fn http_request(
&self,
method: &str,
url: &str,
options: HttpRequestOptions,
) -> Result<HttpRequestResult, BoxxkiteError> {
self.client
.http_request(&self.id, method, url, options)
.await
}
pub async fn file_create(
&self,
path: &str,
content: &str,
options: FileOptions,
) -> Result<FileCreateResult, BoxxkiteError> {
self.client
.file_create(&self.id, path, content, options)
.await
}
pub async fn view(&self, path: &str, options: ViewOptions) -> Result<ViewResult, BoxxkiteError> {
self.client.view(&self.id, path, options).await
}
pub async fn str_replace(
&self,
path: &str,
old_str: &str,
new_str: &str,
options: StrReplaceOptions,
) -> Result<StrReplaceResult, BoxxkiteError> {
self.client
.str_replace(&self.id, path, old_str, new_str, options)
.await
}
pub async fn ls(&self, options: LsOptions) -> Result<LsResult, BoxxkiteError> {
self.client.ls(&self.id, options).await
}
pub async fn glob(
&self,
pattern: &str,
options: GlobOptions,
) -> Result<GlobResult, BoxxkiteError> {
self.client.glob(&self.id, pattern, options).await
}
pub async fn grep(
&self,
pattern: &str,
options: GrepOptions,
) -> Result<GrepResult, BoxxkiteError> {
self.client.grep(&self.id, pattern, options).await
}
pub async fn get_log(&self, options: GetLogOptions) -> Result<AuditLogResponse, BoxxkiteError> {
self.client.get_log(&self.id, options).await
}
pub fn watch(
&self,
) -> Pin<Box<dyn Stream<Item = Result<AuditLogEntry, BoxxkiteError>> + Send + 'static>> {
self.client.watch(&self.id)
}
pub async fn start_process(
&self,
command: &str,
options: StartProcessOptions,
) -> Result<ProcessStartResult, BoxxkiteError> {
self.client.start_process(&self.id, command, options).await
}
pub async fn list_processes(&self) -> Result<ProcessListResult, BoxxkiteError> {
self.client.list_processes(&self.id).await
}
pub async fn get_process_output(
&self,
process_id: &str,
since_offset: i64,
) -> Result<ProcessOutputResult, BoxxkiteError> {
self.client
.get_process_output(&self.id, process_id, since_offset)
.await
}
pub async fn send_process_input(
&self,
process_id: &str,
data: &str,
) -> Result<ProcessInputResult, BoxxkiteError> {
self.client
.send_process_input(&self.id, process_id, data)
.await
}
pub async fn stop_process(&self, process_id: &str) -> Result<ProcessStopResult, BoxxkiteError> {
self.client.stop_process(&self.id, process_id).await
}
pub async fn takeover(&self) -> Result<TakeoverStream, BoxxkiteError> {
self.client.takeover(&self.id).await
}
pub async fn desktop_takeover(&self) -> Result<DesktopStream, BoxxkiteError> {
self.client.desktop_takeover(&self.id).await
}
pub async fn create_preview_url(
&self,
port: u16,
ttl_seconds: Option<u32>,
) -> Result<PreviewUrl, BoxxkiteError> {
self.client
.create_preview_url(&self.id, port, ttl_seconds)
.await
}
pub async fn revoke_preview_url(
&self,
port: u16,
token_id: &str,
) -> Result<PreviewRevokeResult, BoxxkiteError> {
self.client
.revoke_preview_url(&self.id, port, token_id)
.await
}
pub async fn lsp_start(&self, language: &str) -> Result<LspStartResult, BoxxkiteError> {
self.client.lsp_start(&self.id, language).await
}
pub async fn lsp_open(
&self,
lsp_id: &str,
path: &str,
content: &str,
) -> Result<LspOpenResult, BoxxkiteError> {
self.client.lsp_open(&self.id, lsp_id, path, content).await
}
pub async fn lsp_completion(
&self,
lsp_id: &str,
path: &str,
line: u32,
character: u32,
) -> Result<LspCompletionResult, BoxxkiteError> {
self.client
.lsp_completion(&self.id, lsp_id, path, line, character)
.await
}
pub async fn lsp_stop(&self, lsp_id: &str) -> Result<LspStopResult, BoxxkiteError> {
self.client.lsp_stop(&self.id, lsp_id).await
}
}
impl Client {
pub async fn with_sandbox<F, Fut, T>(
&self,
options: CreateSandboxOptions,
f: F,
) -> Result<T, BoxxkiteError>
where
F: FnOnce(SandboxSession) -> Fut,
Fut: Future<Output = Result<T, BoxxkiteError>>,
{
let sandbox = self.create_sandbox(options).await?;
let session = SandboxSession {
client: self.clone(),
id: sandbox.id.clone(),
};
let result = f(session).await;
let _ = self.destroy_sandbox(&sandbox.id).await;
result
}
}