@hasna/sandboxes 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/mcp/index.js +39 -3
  2. package/package.json +1 -1
package/dist/mcp/index.js CHANGED
@@ -5942,8 +5942,10 @@ server.tool("exec_command", "Execute a command in a sandbox", {
5942
5942
  const provider = await getProvider(sandbox.provider);
5943
5943
  const callEnv = { ...sandbox.env_vars, ...params.env_vars };
5944
5944
  const env = Object.keys(callEnv).length > 0 ? callEnv : undefined;
5945
+ const needsShell = /<<\s*['"]?[A-Z]+['"]?/.test(params.command);
5946
+ const effectiveCommand = needsShell ? `bash -c ${JSON.stringify(params.command)}` : params.command;
5945
5947
  if (params.background) {
5946
- provider.exec(sandbox.provider_sandbox_id, params.command, {
5948
+ provider.exec(sandbox.provider_sandbox_id, effectiveCommand, {
5947
5949
  onStdout: collector.onStdout,
5948
5950
  onStderr: collector.onStderr,
5949
5951
  env,
@@ -5955,9 +5957,13 @@ server.tool("exec_command", "Execute a command in a sandbox", {
5955
5957
  }).catch(() => {
5956
5958
  finalizeSessionFailure(session.id);
5957
5959
  });
5958
- return ok({ session_id: session.id, background: true });
5960
+ return ok({
5961
+ session_id: session.id,
5962
+ background: true,
5963
+ message: "Command started in background. Use get_session to check completion status and exit_code. Use bg_wait_session to block until done."
5964
+ });
5959
5965
  }
5960
- const result = await provider.exec(sandbox.provider_sandbox_id, params.command, {
5966
+ const result = await provider.exec(sandbox.provider_sandbox_id, effectiveCommand, {
5961
5967
  onStdout: collector.onStdout,
5962
5968
  onStderr: collector.onStderr,
5963
5969
  env,
@@ -6047,6 +6053,36 @@ server.tool("get_session", "Get session details and exit code (useful for pollin
6047
6053
  return err(e);
6048
6054
  }
6049
6055
  });
6056
+ server.tool("bg_wait_session", "Wait (poll) for a background command session to complete. Returns exit_code, stdout, stderr when done. Use after exec_command with background:true.", {
6057
+ session_id: exports_external.string().describe("Session ID from exec_command background:true response"),
6058
+ timeout_seconds: exports_external.number().optional().describe("Max seconds to wait (default: 300)"),
6059
+ poll_interval_ms: exports_external.number().optional().describe("Poll interval in ms (default: 1000)")
6060
+ }, async (params) => {
6061
+ try {
6062
+ const timeoutMs = (params.timeout_seconds ?? 300) * 1000;
6063
+ const pollMs = params.poll_interval_ms ?? 1000;
6064
+ const deadline = Date.now() + timeoutMs;
6065
+ while (Date.now() < deadline) {
6066
+ const session = getSession(params.session_id);
6067
+ if (session.status === "completed" || session.status === "failed" || session.status === "killed") {
6068
+ const events = listEvents({ session_id: session.id, limit: 1e4 });
6069
+ const stdout = events.filter((e) => e.type === "stdout").map((e) => e.data).join("");
6070
+ const stderr = events.filter((e) => e.type === "stderr").map((e) => e.data).join("");
6071
+ return ok({
6072
+ session_id: session.id,
6073
+ status: session.status,
6074
+ exit_code: session.exit_code ?? (session.status === "failed" || session.status === "killed" ? 1 : 0),
6075
+ stdout,
6076
+ stderr
6077
+ });
6078
+ }
6079
+ await new Promise((r) => setTimeout(r, pollMs));
6080
+ }
6081
+ return err(`Session ${params.session_id} did not complete within ${params.timeout_seconds ?? 300}s`);
6082
+ } catch (e) {
6083
+ return err(e);
6084
+ }
6085
+ });
6050
6086
  server.tool("get_logs", "Get sandbox/session event logs", {
6051
6087
  sandbox_id: exports_external.string().optional().describe("Filter by sandbox ID"),
6052
6088
  session_id: exports_external.string().optional().describe("Filter by session ID"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/sandboxes",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "author": "Andrei Hasna <andrei@hasna.com>",
5
5
  "repository": {
6
6
  "type": "git",