mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-07-09 17:18:34 +00:00
feat(local): warn users before executing commands on their machine (#3433)
## Summary - Replaces the openclaw-only local installation warning with a universal warning that applies to **all** agents spawned locally - Presents users with a 3-option selector before proceeding: - **Ok** — execute directly on this machine (no change in behavior) - **Sandbox** — inject `--beta sandbox` so the agent runs inside a Docker container instead of on the host - **Cancel** — abort the operation - Warning is skipped when sandbox mode is already active or in non-interactive/headless mode (`SPAWN_NON_INTERACTIVE=1`) - When "Sandbox" is selected, `SPAWN_BETA` env var is updated *before* agent/runner resolution so the Docker-wrapped runner is used correctly ## Test plan - [x] `biome lint` — 203 files, 0 issues - [x] `biome check` — formatting clean - [x] Build compiles without errors - [x] 97 orchestrate/sandbox tests pass - [ ] Manual: `spawn <agent> local` shows warning with Ok/Sandbox/Cancel - [ ] Manual: selecting Ok proceeds normally - [ ] Manual: selecting Sandbox enables Docker container mode - [ ] Manual: selecting Cancel exits cleanly - [ ] Manual: `--beta sandbox` skips the warning entirely - [ ] Manual: headless/non-interactive mode skips the warning
This commit is contained in:
parent
08223209a4
commit
c21a65b777
1 changed files with 39 additions and 20 deletions
|
|
@ -37,6 +37,45 @@ import {
|
|||
* host (the `local` cloud).
|
||||
*/
|
||||
export async function runLocalAgent(agentName: string, useSandbox: boolean): Promise<void> {
|
||||
// Warn that local spawning executes commands directly on the user's machine.
|
||||
// Skip in non-interactive mode (headless / CI) and when sandbox is already active.
|
||||
if (!useSandbox && process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
process.stderr.write("\n");
|
||||
logWarn("⚠ Local execution warning");
|
||||
logWarn(" Spawning locally will execute commands directly on this machine.");
|
||||
logWarn(" The agent will have full access to your filesystem, shell, and network.\n");
|
||||
|
||||
const action = await p.select<"ok" | "sandbox" | "cancel">({
|
||||
message: "How would you like to proceed?",
|
||||
options: [
|
||||
{
|
||||
value: "ok",
|
||||
label: "Ok",
|
||||
hint: "proceed — execute directly on this machine",
|
||||
},
|
||||
{
|
||||
value: "sandbox",
|
||||
label: "Sandbox",
|
||||
hint: "run inside a Docker container instead",
|
||||
},
|
||||
{
|
||||
value: "cancel",
|
||||
label: "Cancel",
|
||||
hint: "abort the operation",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (p.isCancel(action) || action === "cancel") {
|
||||
p.log.info("Operation cancelled.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (action === "sandbox") {
|
||||
return runLocalAgent(agentName, true);
|
||||
}
|
||||
}
|
||||
|
||||
const baseRunner = {
|
||||
runServer: runLocal,
|
||||
uploadFile: async (l: string, r: string) => uploadFile(l, r),
|
||||
|
|
@ -55,26 +94,6 @@ export async function runLocalAgent(agentName: string, useSandbox: boolean): Pro
|
|||
await ensureDocker();
|
||||
}
|
||||
|
||||
// Warn about security implications of installing OpenClaw locally
|
||||
// (skip warning in sandbox mode — the container provides isolation)
|
||||
if (agentName === "openclaw" && !useSandbox && process.env.SPAWN_NON_INTERACTIVE !== "1") {
|
||||
process.stderr.write("\n");
|
||||
logWarn("⚠ Local installation warning");
|
||||
logWarn(` This will install ${agent.name} directly on your machine.`);
|
||||
logWarn(" The agent will have full access to your filesystem, shell, and network.");
|
||||
logWarn(" For isolation, consider running on a cloud VM instead.\n");
|
||||
|
||||
const confirmed = await p.confirm({
|
||||
message: "Continue with local installation?",
|
||||
initialValue: true,
|
||||
});
|
||||
|
||||
if (p.isCancel(confirmed) || !confirmed) {
|
||||
p.log.info("Installation cancelled.");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
const cloud: CloudOrchestrator = {
|
||||
cloudName: "local",
|
||||
cloudLabel: useSandbox ? "local (sandboxed)" : "local",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue