fluers_runtime/sandbox.rs
1//! Sandbox backends.
2//!
3//! A [`Sandbox`] manufactures a fresh [`SessionEnv`](crate::SessionEnv) for a
4//! session. Flue ships three flavours — *virtual*, *local*, and *remote
5//! container* — selected via `local()` / container providers. This crate
6//! implements the local flavour (see [`LocalSessionEnv`]); virtual + remote
7//! are stubbed for later phases (see `PORTING_PLAN.md`).
8//!
9//! [`LocalSessionEnv`]: crate::LocalSessionEnv
10
11use async_trait::async_trait;
12use std::path::{Path, PathBuf};
13use std::sync::Arc;
14
15use crate::env::{Limits, SessionEnv};
16use crate::error::RuntimeResult;
17use crate::local_env::LocalSessionEnv;
18
19/// A factory that produces a [`SessionEnv`] for one session.
20#[async_trait]
21pub trait Sandbox: Send + Sync {
22 /// Human-readable name (e.g. `local`, `virtual`, `e2b`).
23 fn name(&self) -> &str;
24
25 /// Build the environment for a session rooted at `workdir`.
26 async fn env_for(&self, workdir: &Path) -> RuntimeResult<Arc<dyn SessionEnv>>;
27}
28
29/// A local-filesystem sandbox: tools run against a real directory on disk.
30///
31/// This is the Rust equivalent of Flue's `local()` from
32/// `@flue/runtime/node`.
33pub struct LocalSandbox {
34 root: PathBuf,
35 limits: Limits,
36}
37
38impl LocalSandbox {
39 /// Create a local sandbox rooted at `root`.
40 #[must_use]
41 pub fn new(root: impl Into<PathBuf>) -> Self {
42 Self {
43 root: root.into(),
44 limits: Limits::default(),
45 }
46 }
47
48 /// Override the default resource limits.
49 #[must_use]
50 pub fn with_limits(mut self, limits: Limits) -> Self {
51 self.limits = limits;
52 self
53 }
54}
55
56#[async_trait]
57impl Sandbox for LocalSandbox {
58 fn name(&self) -> &str {
59 "local"
60 }
61
62 async fn env_for(&self, _workdir: &Path) -> RuntimeResult<Arc<dyn SessionEnv>> {
63 // The sandbox's configured root is the session root; the `workdir`
64 // override is honored by direct `LocalSessionEnv::new` callers.
65 Ok(Arc::new(
66 LocalSessionEnv::new(&self.root, self.limits).await?,
67 ))
68 }
69}
70
71/// Convenience constructor matching Flue's `local()` import.
72#[must_use]
73pub fn local() -> LocalSandbox {
74 LocalSandbox::new(std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")))
75}