MCPcopy Create free account
hub / github.com/NVIDIA/OpenShell / handle_exec_sandbox

Function handle_exec_sandbox

crates/openshell-server/src/grpc/sandbox.rs:803–878  ·  view source on GitHub ↗
(
    state: &Arc<ServerState>,
    request: Request<ExecSandboxRequest>,
)

Source from the content-addressed store, hash-verified

801// ---------------------------------------------------------------------------
802
803pub(super) async fn handle_exec_sandbox(
804 state: &Arc<ServerState>,
805 request: Request<ExecSandboxRequest>,
806) -> Result<Response<ReceiverStream<Result<ExecSandboxEvent, Status>>>, Status> {
807 use openshell_core::ObjectId;
808
809 let req = request.into_inner();
810 if req.sandbox_id.is_empty() {
811 return Err(Status::invalid_argument("sandbox_id is required"));
812 }
813 if req.command.is_empty() {
814 return Err(Status::invalid_argument("command is required"));
815 }
816 if req.environment.keys().any(|key| !is_valid_env_key(key)) {
817 return Err(Status::invalid_argument(
818 "environment keys must match ^[A-Za-z_][A-Za-z0-9_]*$",
819 ));
820 }
821 validate_exec_request_fields(&req)?;
822
823 let sandbox = state
824 .store
825 .get_message::<Sandbox>(&req.sandbox_id)
826 .await
827 .map_err(|e| Status::internal(format!("fetch sandbox failed: {e}")))?
828 .ok_or_else(|| Status::not_found("sandbox not found"))?;
829
830 if SandboxPhase::try_from(sandbox.phase()).ok() != Some(SandboxPhase::Ready) {
831 return Err(Status::failed_precondition("sandbox is not ready"));
832 }
833
834 // Open a relay channel through the supervisor session. Use a 15s
835 // session-wait timeout, enough to cover a transient supervisor reconnect
836 // while still failing quickly during normal operation.
837 let (channel_id, relay_rx) = state
838 .supervisor_sessions
839 .open_relay(sandbox.object_id(), std::time::Duration::from_secs(15))
840 .await
841 .map_err(|e| Status::unavailable(format!("supervisor relay failed: {e}")))?;
842
843 let command_str = build_remote_exec_command(&req)
844 .map_err(|e| Status::invalid_argument(format!("command construction failed: {e}")))?;
845 let stdin_payload = req.stdin;
846 let timeout_seconds = req.timeout_seconds;
847 let request_tty = req.tty;
848
849 let sandbox_id = sandbox.object_id().to_string();
850
851 let (tx, rx) = mpsc::channel::<Result<ExecSandboxEvent, Status>>(256);
852 tokio::spawn(async move {
853 // Wait for the supervisor's reverse CONNECT to deliver the relay stream.
854 let Some(relay_stream) =
855 await_relay_stream(relay_rx, &tx, &sandbox_id, &channel_id, "ExecSandbox").await
856 else {
857 return;
858 };
859
860 if let Err(err) = stream_exec_over_relay(

Callers 1

exec_sandboxMethod · 0.85

Calls 10

is_valid_env_keyFunction · 0.85
await_relay_streamFunction · 0.85
stream_exec_over_relayFunction · 0.85
open_relayMethod · 0.80
object_idMethod · 0.80
spawnFunction · 0.50
is_emptyMethod · 0.45
phaseMethod · 0.45

Tested by

no test coverage detected