Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions docs/reference/commands-nemohermes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -573,17 +573,27 @@ Everything after `--` is forwarded verbatim to the sandbox command, including fl

The exit code is the remote command's exit code.

By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.

```bash
printf 'hello\n' | nemohermes my-assistant exec --stdin -- cat
ssh dgx-spark 'nemohermes my-assistant exec --no-stdin -- pwd'
```

The OpenShell exec endpoint rejects any command argument (the values after `--`) that contains a newline or carriage return, so multi-line commands such as a `bash` heredoc cannot be passed through `exec`.
NemoClaw detects this before dispatch, names the offending argument position, and exits with status `2` instead of surfacing the lower-level OpenShell `InvalidArgument` error.
Join the statements with semicolons (`nemohermes <name> exec -- bash -lc "cmd1; cmd2"`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | nemohermes <name> exec -- bash`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | nemohermes <name> exec --stdin -- bash`).
Or write the script to a file in the sandbox and run it (`nemohermes <name> exec -- bash <script-path>`).

| Flag | Description |
|------|-------------|
| `--workdir <dir>` | Working directory inside the sandbox. The directory is checked before the command runs; if it does not exist, NemoClaw reports `error: --workdir: <dir> does not exist inside the sandbox` and exits with status `1` without invoking the inner command. |
| `--tty` / `--no-tty` | Allocate a pseudo-terminal; defaults to auto-detection (on when stdin and stdout are terminals) |
| `--timeout <seconds>` | Timeout in seconds (`0` means no timeout) |
| `--stdin` / `--no-stdin` | Force caller stdin forwarding or closure (default: inherit terminal stdin; close non-terminal or unavailable stdin). |
Comment on lines +576 to +596

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Imprecise wording: "close terminal stdin explicitly."

--no-stdin forces stdin: false and always maps to ["ignore", "inherit", "inherit"] regardless of whether stdin is a terminal — it closes stdin unconditionally, not just terminal stdin. The current phrasing could mislead users into thinking --no-stdin is a no-op for piped/non-terminal stdin.

📝 Proposed wording fix
-Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.
+Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close stdin explicitly.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.
```bash
printf 'hello\n' | nemohermes my-assistant exec --stdin -- cat
ssh dgx-spark 'nemohermes my-assistant exec --no-stdin -- pwd'
```
The OpenShell exec endpoint rejects any command argument (the values after `--`) that contains a newline or carriage return, so multi-line commands such as a `bash` heredoc cannot be passed through `exec`.
NemoClaw detects this before dispatch, names the offending argument position, and exits with status `2` instead of surfacing the lower-level OpenShell `InvalidArgument` error.
Join the statements with semicolons (`nemohermes <name> exec -- bash -lc "cmd1; cmd2"`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | nemohermes <name> exec -- bash`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | nemohermes <name> exec --stdin -- bash`).
Or write the script to a file in the sandbox and run it (`nemohermes <name> exec -- bash <script-path>`).
| Flag | Description |
|------|-------------|
| `--workdir <dir>` | Working directory inside the sandbox. The directory is checked before the command runs; if it does not exist, NemoClaw reports `error: --workdir: <dir> does not exist inside the sandbox` and exits with status `1` without invoking the inner command. |
| `--tty` / `--no-tty` | Allocate a pseudo-terminal; defaults to auto-detection (on when stdin and stdout are terminals) |
| `--timeout <seconds>` | Timeout in seconds (`0` means no timeout) |
| `--stdin` / `--no-stdin` | Force caller stdin forwarding or closure (default: inherit terminal stdin; close non-terminal or unavailable stdin). |
By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close stdin explicitly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/reference/commands-nemohermes.mdx` around lines 576 - 596, The stdin
flag description is imprecise: `--no-stdin` does not just “close terminal stdin
explicitly,” it always forces stdin off via `ExecOptions`/`stdin: false` and
maps to the ignore/inherit/inherit behavior regardless of terminal state. Update
the wording in the `commands-nemohermes` docs near the `--stdin` / `--no-stdin`
entry and the introductory paragraph to say `--stdin` forwards an intentional
pipe, while `--no-stdin` unconditionally closes stdin. Keep the existing default
behavior description for inherited terminal stdin and non-terminal stdin
closure.


### `nemohermes <name> agent`

Expand Down Expand Up @@ -834,14 +844,19 @@ Use `--` to separate `exec` options from the command you want to run inside the
The command exits with the remote command's exit code.

```bash
nemohermes my-assistant exec [--workdir <dir>] [--tty|--no-tty] [--timeout <s>] -- <cmd> [args...]
nemohermes my-assistant exec [--workdir <dir>] [--tty|--no-tty] [--timeout <s>] [--stdin|--no-stdin] -- <cmd> [args...]
```

By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.

| Flag | Description |
|------|-------------|
| `--workdir <dir>` | Set the working directory inside the sandbox. The directory is checked before the command runs; if it does not exist, NemoClaw reports `error: --workdir: <dir> does not exist inside the sandbox` and exits with status `1` without invoking the inner command. |
| `--tty`, `--no-tty` | Allocate or disable a pseudo-terminal; defaults to auto-detection |
| `--timeout <s>` | Timeout in seconds. Use `0` for no timeout |
| `--stdin`, `--no-stdin` | Force caller stdin forwarding or closure (default: inherit terminal stdin; close non-terminal or unavailable stdin). |

### `nemohermes <name> logs`

Expand Down
19 changes: 17 additions & 2 deletions docs/reference/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -703,17 +703,27 @@ The exit code is the remote command's exit code.

</AgentOnly>

By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.

```bash
printf 'hello\n' | $$nemoclaw my-assistant exec --stdin -- cat
ssh dgx-spark '$$nemoclaw my-assistant exec --no-stdin -- pwd'
```

The OpenShell exec endpoint rejects any command argument (the values after `--`) that contains a newline or carriage return, so multi-line commands such as a `bash` heredoc cannot be passed through `exec`.
NemoClaw detects this before dispatch, names the offending argument position, and exits with status `2` instead of surfacing the lower-level OpenShell `InvalidArgument` error.
Join the statements with semicolons (`$$nemoclaw <name> exec -- bash -lc "cmd1; cmd2"`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | $$nemoclaw <name> exec -- bash`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | $$nemoclaw <name> exec --stdin -- bash`).
Or write the script to a file in the sandbox and run it (`$$nemoclaw <name> exec -- bash <script-path>`).

| Flag | Description |
|------|-------------|
| `--workdir <dir>` | Working directory inside the sandbox. The directory is checked before the command runs; if it does not exist, NemoClaw reports `error: --workdir: <dir> does not exist inside the sandbox` and exits with status `1` without invoking the inner command. |
| `--tty` / `--no-tty` | Allocate a pseudo-terminal; defaults to auto-detection (on when stdin and stdout are terminals) |
| `--timeout <seconds>` | Timeout in seconds (`0` means no timeout) |
| `--stdin` / `--no-stdin` | Force caller stdin forwarding or closure (default: inherit terminal stdin; close non-terminal or unavailable stdin). |
Comment on lines +706 to +726

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Same imprecise wording: "close terminal stdin explicitly."

Per shouldInheritSandboxExecStdin in src/lib/actions/sandbox/exec-stdio.ts, an explicit --no-stdin bypasses TTY detection and always closes stdin, not just terminal stdin. Since this page is the source that commands-nemohermes.mdx is regenerated from, fixing the wording here should also propagate to the Hermes variant.

📝 Proposed wording fix
-Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.
+Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close stdin explicitly.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.
```bash
printf 'hello\n' | $$nemoclaw my-assistant exec --stdin -- cat
ssh dgx-spark '$$nemoclaw my-assistant exec --no-stdin -- pwd'
```
The OpenShell exec endpoint rejects any command argument (the values after `--`) that contains a newline or carriage return, so multi-line commands such as a `bash` heredoc cannot be passed through `exec`.
NemoClaw detects this before dispatch, names the offending argument position, and exits with status `2` instead of surfacing the lower-level OpenShell `InvalidArgument` error.
Join the statements with semicolons (`$$nemoclaw <name> exec -- bash -lc "cmd1; cmd2"`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | $$nemoclaw <name> exec -- bash`).
Pipe the script into the sandbox shell over stdin (`printf 'cmd1\ncmd2\n' | $$nemoclaw <name> exec --stdin -- bash`).
Or write the script to a file in the sandbox and run it (`$$nemoclaw <name> exec -- bash <script-path>`).
| Flag | Description |
|------|-------------|
| `--workdir <dir>` | Working directory inside the sandbox. The directory is checked before the command runs; if it does not exist, NemoClaw reports `error: --workdir: <dir> does not exist inside the sandbox` and exits with status `1` without invoking the inner command. |
| `--tty` / `--no-tty` | Allocate a pseudo-terminal; defaults to auto-detection (on when stdin and stdout are terminals) |
| `--timeout <seconds>` | Timeout in seconds (`0` means no timeout) |
| `--stdin` / `--no-stdin` | Force caller stdin forwarding or closure (default: inherit terminal stdin; close non-terminal or unavailable stdin). |
By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close stdin explicitly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/reference/commands.mdx` around lines 706 - 726, Update the stdin flag
description in commands.mdx to match shouldInheritSandboxExecStdin in
src/lib/actions/sandbox/exec-stdio.ts: explicit --no-stdin always closes stdin,
not just terminal stdin. Adjust the wording in the exec docs table and the
surrounding prose so it says default behavior only inherits terminal stdin,
while --no-stdin forces stdin closure regardless of TTY state; this source
should then regenerate the Hermes variant correctly.


### `$$nemoclaw <name> agent`

Expand Down Expand Up @@ -1083,14 +1093,19 @@ The command exits with the remote command's exit code.
</AgentOnly>

```bash
$$nemoclaw my-assistant exec [--workdir <dir>] [--tty|--no-tty] [--timeout <s>] -- <cmd> [args...]
$$nemoclaw my-assistant exec [--workdir <dir>] [--tty|--no-tty] [--timeout <s>] [--stdin|--no-stdin] -- <cmd> [args...]
```

By default, NemoClaw inherits caller stdin only when it is a terminal.
Non-terminal or unavailable stdin is closed so SSH, CI, and other one-shot commands cannot wait on an inherited pipe.
Pass `--stdin` to forward an intentional pipe, or `--no-stdin` to close terminal stdin explicitly.

| Flag | Description |
|------|-------------|
| `--workdir <dir>` | Set the working directory inside the sandbox. The directory is checked before the command runs; if it does not exist, NemoClaw reports `error: --workdir: <dir> does not exist inside the sandbox` and exits with status `1` without invoking the inner command. |
| `--tty`, `--no-tty` | Allocate or disable a pseudo-terminal; defaults to auto-detection |
| `--timeout <s>` | Timeout in seconds. Use `0` for no timeout |
| `--stdin`, `--no-stdin` | Force caller stdin forwarding or closure (default: inherit terminal stdin; close non-terminal or unavailable stdin). |

### `$$nemoclaw <name> logs`

Expand Down
40 changes: 37 additions & 3 deletions src/commands/sandbox/exec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe("SandboxExecCommand oclif parse path", () => {
expect(execSandboxMock).toHaveBeenCalledWith(
"alpha",
["openclaw", "agent", "--agent", "main", "-m", "hi"],
{ workdir: undefined, tty: null, timeoutSeconds: undefined },
{ workdir: undefined, tty: null, timeoutSeconds: undefined, stdin: undefined },
);
});

Expand All @@ -38,6 +38,7 @@ describe("SandboxExecCommand oclif parse path", () => {
workdir: "/sandbox/workspace",
tty: null,
timeoutSeconds: undefined,
stdin: undefined,
});
});

Expand All @@ -51,6 +52,7 @@ describe("SandboxExecCommand oclif parse path", () => {
workdir: undefined,
tty: null,
timeoutSeconds: undefined,
stdin: undefined,
});
});

Expand All @@ -62,7 +64,7 @@ describe("SandboxExecCommand oclif parse path", () => {
expect(execSandboxMock).toHaveBeenCalledWith(
"alpha",
["bash", "-lc", "echo line1; echo line2"],
{ workdir: undefined, tty: null, timeoutSeconds: undefined },
{ workdir: undefined, tty: null, timeoutSeconds: undefined, stdin: undefined },
);
});

Expand All @@ -74,7 +76,7 @@ describe("SandboxExecCommand oclif parse path", () => {
expect(execSandboxMock).toHaveBeenCalledWith(
"alpha",
["bash", "-lc", "echo line1; echo line2"],
{ workdir: "/sandbox", tty: null, timeoutSeconds: undefined },
{ workdir: "/sandbox", tty: null, timeoutSeconds: undefined, stdin: undefined },
);
});

Expand All @@ -84,6 +86,7 @@ describe("SandboxExecCommand oclif parse path", () => {
workdir: undefined,
tty: true,
timeoutSeconds: 30,
stdin: undefined,
});
execSandboxMock.mockReset();

Expand All @@ -92,6 +95,37 @@ describe("SandboxExecCommand oclif parse path", () => {
workdir: undefined,
tty: false,
timeoutSeconds: undefined,
stdin: undefined,
});
});

it("parses --stdin as explicit stdin forwarding", async () => {
await SandboxExecCommand.run(["alpha", "--stdin", "--", "cat"], rootDir);
expect(execSandboxMock).toHaveBeenCalledWith("alpha", ["cat"], {
workdir: undefined,
tty: null,
timeoutSeconds: undefined,
stdin: true,
});
});

it("parses --no-stdin as explicit stdin closure", async () => {
await SandboxExecCommand.run(["alpha", "--no-stdin", "--", "pwd"], rootDir);
expect(execSandboxMock).toHaveBeenCalledWith("alpha", ["pwd"], {
workdir: undefined,
tty: null,
timeoutSeconds: undefined,
stdin: false,
});
});

it("leaves stdin mode unset for the production spawner to auto-detect", async () => {
await SandboxExecCommand.run(["alpha", "--", "bash"], rootDir);
expect(execSandboxMock).toHaveBeenCalledWith("alpha", ["bash"], {
workdir: undefined,
tty: null,
timeoutSeconds: undefined,
stdin: undefined,
});
});
});
13 changes: 11 additions & 2 deletions src/commands/sandbox/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ export default class SandboxExecCommand extends NemoClawCommand {
static strict = false;
static summary = "Run a command non-interactively in a running sandbox";
static description =
"Run a single command inside a running sandbox via the OpenShell exec endpoint. The command runs as the sandbox user (HOME=/sandbox) and exits with the remote command's exit code. Use `--` to separate exec options from the user command.";
static usage = ["<name> [--workdir <dir>] [--tty|--no-tty] [--timeout <s>] -- <cmd> [args...]"];
"Run a single command inside a running sandbox via the OpenShell exec endpoint. The command runs as the sandbox user (HOME=/sandbox) and exits with the remote command's exit code. Use `--` to separate exec options from the user command. Stdin is inherited by default only when it is a terminal; pass `--stdin` to forward an intentional pipe.";
static usage = [
"<name> [--workdir <dir>] [--tty|--no-tty] [--timeout <s>] [--stdin|--no-stdin] -- <cmd> [args...]",
];
static examples = [
"<%= config.bin %> sandbox exec alpha -- openclaw agent --agent main -m hi",
"<%= config.bin %> sandbox exec alpha --workdir /sandbox -- ls -la",
"printf 'hello' | <%= config.bin %> sandbox exec alpha --stdin -- cat",
];
static args = {
sandboxName: Args.string({ name: "sandbox", description: "Sandbox name", required: true }),
Expand All @@ -29,6 +32,11 @@ export default class SandboxExecCommand extends NemoClawCommand {
min: 0,
description: "Timeout in seconds (0 = no timeout)",
}),
stdin: Flags.boolean({
allowNo: true,
description:
"Pass caller stdin through to the sandbox command; defaults to terminal stdin only",
}),
};

public async run(): Promise<void> {
Expand All @@ -38,6 +46,7 @@ export default class SandboxExecCommand extends NemoClawCommand {
workdir: flags.workdir,
tty: typeof flags.tty === "boolean" ? flags.tty : null,
timeoutSeconds: flags.timeout,
stdin: flags.stdin,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ describe("runSandboxExecCommand mutable OpenClaw cleanup (#6047)", () => {
"alpha",
["sleep", "30"],
{},
(binary, args) => runSandboxExecChild(binary, args, () => child, signalSource),
(binary, args) => runSandboxExecChild(binary, args, {}, () => child, signalSource),
cleanupDeps({ inspectMutableConfigPerms: inspect }),
);
signalEvents.emit(signal);
Expand Down Expand Up @@ -282,7 +282,7 @@ describe("runSandboxExecCommand mutable OpenClaw cleanup (#6047)", () => {
"alpha",
["sleep", "30"],
{},
(binary, args) => runSandboxExecChild(binary, args, () => child, signalSource),
(binary, args) => runSandboxExecChild(binary, args, {}, () => child, signalSource),
cleanupDeps({ inspectMutableConfigPerms: inspect }),
);
signalEvents.emit("SIGINT");
Expand Down
7 changes: 4 additions & 3 deletions src/lib/actions/sandbox/exec-policy-hint-emission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ function defaultProbeLogs(sandboxName: string): string {
/**
* Emit a denial-adjacent hint after a failed exec. Every dependency is
* best-effort: failures return null and never replace the command's exit code.
* Exec inherits stdio byte-for-byte, so proxy error text is intentionally not
* captured for a cheaper prefilter; nonzero status is the only safe pre-probe
* gate, and the timestamp-correlated structured denial is the confirmation.
* Exec leaves stdout and stderr inherited byte-for-byte, so proxy error text is
* intentionally not captured for a cheaper prefilter; nonzero status is the
* only safe pre-probe gate, and the timestamp-correlated structured denial is
* the confirmation.
* Log-read failures are terminal rather than retried, while successful empty
* reads get two 120 ms settling retries (240 ms total).
*/
Expand Down
35 changes: 35 additions & 0 deletions src/lib/actions/sandbox/exec-stdio.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { describe, expect, it } from "vitest";
import { buildSandboxExecStdio, shouldInheritSandboxExecStdin } from "./exec-stdio";

describe("buildSandboxExecStdio", () => {
it("inherits terminal stdin by default", () => {
expect(buildSandboxExecStdio({}, true)).toBe("inherit");
});

it("closes non-terminal or unknown stdin by default", () => {
expect(buildSandboxExecStdio({}, false)).toEqual(["ignore", "inherit", "inherit"]);
expect(buildSandboxExecStdio({}, undefined)).toEqual(["ignore", "inherit", "inherit"]);
});

it("honors explicit flags over terminal detection", () => {
expect(buildSandboxExecStdio({ stdin: true }, false)).toBe("inherit");
expect(buildSandboxExecStdio({ stdin: true }, undefined)).toBe("inherit");
expect(buildSandboxExecStdio({ stdin: false }, true)).toEqual(["ignore", "inherit", "inherit"]);
});
});

describe("shouldInheritSandboxExecStdin", () => {
it("lets explicit --stdin and --no-stdin win", () => {
expect(shouldInheritSandboxExecStdin(true, false)).toBe(true);
expect(shouldInheritSandboxExecStdin(false, true)).toBe(false);
});

it("inherits only a positively identified TTY when no flag is present", () => {
expect(shouldInheritSandboxExecStdin(undefined, true)).toBe(true);
expect(shouldInheritSandboxExecStdin(undefined, false)).toBe(false);
expect(shouldInheritSandboxExecStdin(undefined, undefined)).toBe(false);
});
});
23 changes: 23 additions & 0 deletions src/lib/actions/sandbox/exec-stdio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import type { StdioOptions } from "node:child_process";
import { isStdinTty } from "../../core/stdin";
import type { SandboxExecOptions } from "./exec";

export function shouldInheritSandboxExecStdin(
requested: boolean | undefined,
stdinIsTty: boolean | undefined,
): boolean {
if (typeof requested === "boolean") return requested;
return stdinIsTty === true;
}

export function buildSandboxExecStdio(
options: SandboxExecOptions = {},
stdinIsTty: boolean | undefined = isStdinTty(),
): StdioOptions {
return shouldInheritSandboxExecStdin(options.stdin, stdinIsTty)
? "inherit"
: ["ignore", "inherit", "inherit"];
}
Loading
Loading