pub mod dap;
pub mod eval_kernel;
pub mod shell;
pub use dap::{DapClient, DapDebugService};
pub use eval_kernel::{JavaScriptEvalKernel, PythonEvalKernel};
pub use shell::PersistentShellSession;
use async_trait::async_trait;
use std::time::Duration;
#[derive(Debug, Clone, Default)]
pub struct ShellOutput {
pub stdout: String,
pub stderr: String,
pub exit_code: i32,
pub truncated: bool,
}
#[async_trait]
pub trait ShellSession: Send + Sync + std::fmt::Debug {
async fn execute(&self, command: &str, timeout: Duration) -> Result<ShellOutput, String>;
fn cancel(&self);
async fn reset(&self) -> Result<(), String>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EvalLanguage {
Python,
JavaScript,
}
#[derive(Debug, Clone, Default)]
pub struct EvalOutput {
pub result: String,
pub stdout: String,
pub stderr: String,
pub error: Option<String>,
pub truncated: bool,
}
#[async_trait]
pub trait EvalKernel: Send + Sync + std::fmt::Debug {
fn language(&self) -> EvalLanguage;
async fn execute(&self, code: &str, timeout: Duration) -> Result<EvalOutput, String>;
async fn reset(&self) -> Result<(), String>;
}
#[async_trait]
pub trait DebugService: Send + Sync + std::fmt::Debug {
async fn start(&self, config: &serde_json::Value) -> Result<String, String>;
async fn request(
&self,
session: &str,
command: &str,
args: &serde_json::Value,
) -> Result<serde_json::Value, String>;
async fn terminate(&self, session: &str) -> Result<(), String>;
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[derive(Debug)]
struct NoopShell;
#[async_trait]
impl ShellSession for NoopShell {
async fn execute(&self, _command: &str, _timeout: Duration) -> Result<ShellOutput, String> {
Ok(ShellOutput {
stdout: String::new(),
stderr: String::new(),
exit_code: 0,
truncated: false,
})
}
fn cancel(&self) {}
async fn reset(&self) -> Result<(), String> {
Ok(())
}
}
#[tokio::test]
async fn shell_session_contract_is_object_safe() {
let shell: Arc<dyn ShellSession> = Arc::new(NoopShell);
let out = shell.execute("true", Duration::from_secs(1)).await.unwrap();
assert_eq!(out.exit_code, 0);
shell.cancel();
shell.reset().await.unwrap();
}
}