@hasna/sandboxes 0.1.12 → 0.1.14
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.
- package/dist/cli/index.js +17 -0
- package/dist/mcp/index.js +39 -3
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3932,6 +3932,23 @@ program2.command("delete <id>").description("Delete a sandbox").action(async (id
|
|
|
3932
3932
|
handleError(err);
|
|
3933
3933
|
}
|
|
3934
3934
|
});
|
|
3935
|
+
for (const alias of ["remove", "uninstall", "rm"]) {
|
|
3936
|
+
program2.command(`${alias} <id>`).description(`Delete a sandbox (alias for delete)`).action(async (id) => {
|
|
3937
|
+
try {
|
|
3938
|
+
const sandbox = getSandbox(id);
|
|
3939
|
+
if (sandbox.provider_sandbox_id) {
|
|
3940
|
+
try {
|
|
3941
|
+
const p = await getProvider(sandbox.provider);
|
|
3942
|
+
await p.delete(sandbox.provider_sandbox_id);
|
|
3943
|
+
} catch {}
|
|
3944
|
+
}
|
|
3945
|
+
deleteSandbox(sandbox.id);
|
|
3946
|
+
console.log(chalk.green(`Sandbox ${shortId(sandbox.id)} deleted.`));
|
|
3947
|
+
} catch (err) {
|
|
3948
|
+
handleError(err);
|
|
3949
|
+
}
|
|
3950
|
+
});
|
|
3951
|
+
}
|
|
3935
3952
|
program2.command("logs <id>").description("Show event logs for a sandbox").option("-f, --follow", "Follow log output").option("-s, --session <session_id>", "Filter by session ID").option("-l, --limit <n>", "Max number of events", "50").action(async (id, opts) => {
|
|
3936
3953
|
try {
|
|
3937
3954
|
const sandbox = getSandbox(id);
|
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,
|
|
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({
|
|
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,
|
|
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"),
|