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
28 changes: 28 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,34 @@ reviews:
- path: "test/e2e/test-channels-stop-start.sh"
instructions: *e2e-channel-stop-start

- path: "src/lib/actions/sandbox/sessions/**"
instructions: &e2e-sessions-cli |
This file is part of the host-side OpenClaw sessions management
surface (`nemoclaw <name> sessions list|cleanup|reset|export-trajectory`).
Changes affect session store reads, gateway-delegated `sessions.reset`
wiring, redacted trajectory export bundles, and the path/agent/session
validators shared by those commands.

**E2E test recommendation:**
- `sessions-cli-e2e` — onboard, seed a session, then exercise
`sessions list`, `sessions cleanup --dry-run`,
`sessions export-trajectory --save-host`, and gateway-delegated
`sessions reset`

To run selectively:
```
gh workflow run nightly-e2e.yaml --ref <branch> -f jobs=sessions-cli-e2e
```

- path: "src/commands/sandbox/sessions.ts"
instructions: *e2e-sessions-cli

- path: "src/commands/sandbox/sessions/**"
instructions: *e2e-sessions-cli

- path: "test/e2e/test-sessions-cli.sh"
instructions: *e2e-sessions-cli

- path: "src/lib/actions/inference-set.ts"
instructions: |
This file switches the OpenShell inference route and patches the
Expand Down
31 changes: 30 additions & 1 deletion .github/workflows/nightly-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ on:
credential-sanitization-e2e, telegram-injection-e2e,
overlayfs-autofix-e2e, device-auth-health-e2e,
launchable-smoke-e2e, gpu-e2e, gpu-double-onboard-e2e,
channels-add-remove-e2e, channels-stop-start-e2e, brave-search-e2e
channels-add-remove-e2e, channels-stop-start-e2e, brave-search-e2e,
sessions-cli-e2e
required: false
type: string
default: ""
Expand Down Expand Up @@ -502,6 +503,31 @@ jobs:
secrets:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }}
BRAVE_API_KEY: ${{ secrets.BRAVE_API_KEY }}
# ── Sessions CLI E2E ────────────────────────────────────────────────
# Exercises the host-side `nemoclaw <name> sessions {list,cleanup,reset,export-trajectory}`
# surface against a live sandbox: pass-through to `openclaw sessions list/cleanup`,
# gateway-delegated `sessions reset` via `openclaw gateway call`, and
# `sessions export-trajectory --save-host` wrapping `openclaw sessions export-trajectory`
# plus an `openshell sandbox download` of the bundle.
sessions-cli-e2e:
if: >-
github.repository == 'NVIDIA/NemoClaw' && (github.event_name != 'workflow_dispatch' ||
inputs.jobs == '' ||
contains(format(',{0},', inputs.jobs), ',sessions-cli-e2e,'))
uses: ./.github/workflows/e2e-script.yaml
with:
ref: ${{ inputs.target_ref || github.ref }}
script: test/e2e/test-sessions-cli.sh
timeout_minutes: 60
artifact_name: "install-log-sessions-cli"
artifact_path: |
/tmp/nemoclaw-e2e-install.log
env_json: '{"NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE":"1","NEMOCLAW_NON_INTERACTIVE":"1","NEMOCLAW_SANDBOX_NAME":"e2e-sessions-cli"}'
nvidia_api_key: true
github_token: false
secrets:
NVIDIA_API_KEY: ${{ secrets.NVIDIA_API_KEY }}
BRAVE_API_KEY: ${{ secrets.BRAVE_API_KEY }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# ── Channels stop/start lifecycle E2E (#3462) ───────────────────────
# Regression coverage for #3453 (stop must disable across rebuild), #3381
# (start must re-attach from cached credentials).
Expand Down Expand Up @@ -1927,6 +1953,7 @@ jobs:
issue-4462-gateway-pinned-approval-characterization-e2e,
messaging-compatible-endpoint-e2e,
channels-add-remove-e2e,
sessions-cli-e2e,
channels-stop-start-e2e,
brave-search-e2e,
kimi-inference-compat-e2e,
Expand Down Expand Up @@ -2034,6 +2061,7 @@ jobs:
issue-4462-gateway-pinned-approval-characterization-e2e,
messaging-compatible-endpoint-e2e,
channels-add-remove-e2e,
sessions-cli-e2e,
channels-stop-start-e2e,
brave-search-e2e,
kimi-inference-compat-e2e,
Expand Down Expand Up @@ -2198,6 +2226,7 @@ jobs:
issue-4462-gateway-pinned-approval-characterization-e2e,
messaging-compatible-endpoint-e2e,
channels-add-remove-e2e,
sessions-cli-e2e,
channels-stop-start-e2e,
brave-search-e2e,
kimi-inference-compat-e2e,
Expand Down
3 changes: 3 additions & 0 deletions docs/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ navigation:
- page: "Network Policies"
path: reference/network-policies.mdx
slug: network-policies
- page: "Session Storage Layout"
path: reference/session-storage.mdx
slug: session-storage
- page: "Troubleshooting"
path: reference/troubleshooting.mdx
slug: troubleshooting
Expand Down
111 changes: 111 additions & 0 deletions docs/reference/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,40 @@ $ nemoclaw my-assistant exec [--workdir <dir>] [--tty|--no-tty] [--timeout <s>]
| `--tty`, `--no-tty` | Allocate or disable a pseudo-terminal; defaults to auto-detection |
| `--timeout <s>` | Timeout in seconds. Use `0` for no timeout |

### `nemoclaw <name> download`

Download a file or directory out of a running sandbox to the host.
The command forwards to `openshell sandbox download <name> <sandbox-path> <host-dest>` after a lightweight readiness check, so the file-system semantics — single-file vs. directory copy, target naming, overwrite behaviour — follow OpenShell's transport.
The host destination directory is created if it does not yet exist; if you omit it, the current working directory is used.

```console
$ nemoclaw my-assistant download <sandbox-path> [host-dest]
```

| Argument | Description |
|----------|-------------|
| `<sandbox-path>` | Absolute or sandbox-relative path inside the sandbox (a file or a directory). |
| `[host-dest]` | Host destination directory; defaults to the current working directory. Created if missing. |

Use this command when you need the raw on-disk artefacts from inside a sandbox rather than a NemoClaw- or OpenClaw-curated view of them.
Typical scenarios:

- Pulling raw OpenClaw session files for offline inspection or replay (`/sandbox/.openclaw/sessions/<agent>/` — see [Session Storage Layout](/reference/session-storage) for the on-disk shape):

```console
$ nemoclaw my-assistant download /sandbox/.openclaw/sessions/main ./sessions-out/
```

- Pulling an existing trajectory export bundle that you previously created without `--save-host`:

```console
$ nemoclaw my-assistant download /sandbox/.openclaw/trajectory-exports/<bundle> ./trajectories/
```

- Pulling arbitrary workspace artefacts (logs, configs, generated files) from anywhere inside the sandbox.

Higher-level subcommands such as `sessions export-trajectory --save-host` are convenience wrappers built on the same transport — reach for `download` when you want the raw files without going through OpenClaw's redaction pipeline or bundle layout.

### `nemoclaw <name> logs`

View sandbox logs.
Expand Down Expand Up @@ -831,6 +865,83 @@ Files with unsafe path characters are rejected to prevent shell injection.
If the skill already exists on the sandbox, the command updates it in place and preserves chat history.
For new installs, the agent session index is refreshed so the agent discovers the skill on the next session.

### `nemoclaw <name> sessions`

Inspect and manage OpenClaw conversation sessions stored inside a sandbox.
For the on-disk layout the commands operate on, see [Session Storage Layout](/reference/session-storage).
`<sessionKey>` arguments are the canonical keys as stored in `sessions.json` (`agent:<agentId>:<rest>`).

| Subcommand | Purpose |
|---|---|
| `sessions` | List stored sessions for the configured default agent (forwards to `openclaw sessions`). |
| `sessions list` | Same as the root form. Forwards `--agent`, `--all-agents`, `--active`, `--limit`, `--json`, `--store` to `openclaw sessions list`. |
| `sessions cleanup` | Run OpenClaw's policy-driven store maintenance. Forwards `--dry-run`, `--enforce`, `--agent`, `--all-agents`, `--fix-missing`, `--fix-dm-scope`, `--active-key`, `--json`, `--store`. |
| `sessions reset <agent> <sessionKey> [--reason new\|reset]` | Reset a single session by invoking the OpenClaw gateway `sessions.reset` RPC. |
| `sessions export-trajectory <agent> <sessionKey> [--output <name>] [--workspace <dir>] [--save-host <dir>] [--json]` | Run `openclaw sessions export-trajectory` inside the sandbox and (optionally) copy the resulting bundle to the host via `openshell sandbox download`. |

Comment thread
coderabbitai[bot] marked this conversation as resolved.
```bash
nemoclaw my-assistant sessions list --json
nemoclaw my-assistant sessions cleanup --dry-run
nemoclaw my-assistant sessions reset main agent:main:main
nemoclaw my-assistant sessions reset main agent:main:telegram:thread --reason new
nemoclaw my-assistant sessions export-trajectory main agent:main:main
nemoclaw my-assistant sessions export-trajectory main agent:main:main --save-host ./trajectories/
```

`sessions list` and `sessions cleanup` shell out to `openclaw sessions ...` inside the sandbox via `openshell sandbox exec`, so OpenClaw owns the output format and exit code.
`sessions reset` is a thin host-side wrapper around the upstream `openclaw gateway call sessions.reset` RPC: it goes through `openshell sandbox exec` so the OpenClaw gateway still performs the archive-then-recreate, owns the write lock, and emits the lifecycle event. The NemoClaw host never edits `sessions.json` directly, and you can always invoke the upstream RPC by hand from inside the sandbox if you want to skip this wrapper.
`sessions export-trajectory` runs `openclaw sessions export-trajectory --json` inside the sandbox so OpenClaw owns the redaction pipeline and the on-disk bundle shape; pass `--save-host <dir>` to additionally copy the resolved bundle directory to the host via `openshell sandbox download`.

### `nemoclaw <name> sessions list`

List OpenClaw conversation sessions in a sandbox.
Pass-through to `openclaw sessions list` inside the sandbox via `openshell sandbox exec`; all flags accepted by the in-sandbox CLI (e.g. `--agent`, `--all-agents`, `--active`, `--limit`, `--json`, `--store`) are forwarded verbatim.
OpenClaw owns the output format and exit code.

### `nemoclaw <name> sessions cleanup`

Run OpenClaw session-store maintenance in a sandbox.
Pass-through to `openclaw sessions cleanup` inside the sandbox via `openshell sandbox exec`; all flags accepted by the in-sandbox CLI (e.g. `--dry-run`, `--enforce`, `--agent`, `--all-agents`, `--fix-missing`, `--fix-dm-scope`, `--active-key`, `--json`, `--store`) are forwarded verbatim.
OpenClaw owns the policy and reporting; NemoClaw only routes the call.

### `nemoclaw <name> sessions reset`

Reset an OpenClaw conversation session by invoking the gateway `sessions.reset` RPC.

The official, upstream-supported way to reset a session is the OpenClaw gateway CLI from inside the sandbox:

```bash
openclaw gateway call sessions.reset --params '{"key":"<sessionKey>","reason":"reset"}' --json
```

The upstream RPC params are a closed object: `key` (the canonical `agent:<agentId>:<rest>` session key) and an optional `reason` (`"reset"` or `"new"`); no separate `agent` field is accepted. The gateway parses the target agent out of the key, owns the archival of the prior transcript (`<sessionId>.reset.<timestamp>.jsonl`), holds the write lock on `sessions.json`, and emits the lifecycle event. Any session reset performed outside that RPC — for example, editing `sessions.json` from the host or removing the transcript file directly — risks racing the in-sandbox writer and corrupting the store.

This NemoClaw command is a thin host-side wrapper around that RPC. It accepts `<agent>` and `<sessionKey>` arguments and forwards `{"key": "<sessionKey>", "reason": ...}` verbatim to the gateway via `openshell sandbox exec -- openclaw gateway call sessions.reset --params ... --json`. The `<agent>` argument is used purely for client-side validation: the wrapper rejects the call before it reaches the gateway when `<agent>` disagrees with the agent prefix parsed from `<sessionKey>`, so a typo in the agent id cannot silently route to a different agent's namespace. The NemoClaw host never edits `sessions.json` directly; the wrapper just spares you from typing the JSON params and `openshell sandbox exec` plumbing by hand.

```bash
nemoclaw <name> sessions reset <agent> <sessionKey> [--reason new|reset]
```

| Flag | Description |
|------|-------------|
| `--reason` | `reset` (default) keeps the archive trail bound to the key; `new` registers a brand-new session id without binding the prior transcript. |

### `nemoclaw <name> sessions export-trajectory`

Export a redacted trajectory bundle for an OpenClaw session.
Runs `openclaw sessions export-trajectory --json` inside the sandbox via `openshell sandbox exec`, so OpenClaw owns the redaction pipeline and the bundle layout (`.openclaw/trajectory-exports/<output>/`).

```bash
nemoclaw <name> sessions export-trajectory <agent> <sessionKey> [--output <name>] [--workspace <dir>] [--save-host <dir>] [--json]
```

| Flag | Description |
|------|-------------|
| `--output <name>` | Bundle directory name inside the sandbox's `.openclaw/trajectory-exports`. OpenClaw assigns a name when omitted. |
| `--workspace <dir>` | Sandbox workspace root used to resolve the export base directory. |
| `--save-host <dir>` | Host destination directory; if set, the resolved bundle is downloaded to this path via `openshell sandbox download`. Created if missing. |
| `--json` | Print the OpenClaw export summary as JSON instead of the text status lines. |

### `nemoclaw <name> skill remove <skill>`

Remove an installed skill from a running sandbox by skill name.
Expand Down
Loading
Loading