Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
48fc16c
fix(whatsapp): report the paired in-process bridge in channels status…
hunglp6d Jul 16, 2026
07300cc
Merge branch 'main' of github.com:NVIDIA/NemoClaw into fix/whatsapp-s…
hunglp6d Jul 16, 2026
ede4ffe
fix(whatsapp): read the canonical /tmp/gateway.log for in-process bri…
hunglp6d Jul 16, 2026
bb55301
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 16, 2026
dc3b06d
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 16, 2026
7ee22fa
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 16, 2026
dff0ad1
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 16, 2026
fab911c
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 16, 2026
8001168
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 17, 2026
1acc455
fix(whatsapp): probe live gateway status JSON, not log scraping
hunglp6d Jul 17, 2026
39ba950
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 17, 2026
0156393
fix(whatsapp): harden JSON status probe (epoch range, agent, gateway …
hunglp6d Jul 17, 2026
58d0f12
Merge branch 'fix/whatsapp-status-probe-unpaired' of github.com:NVIDI…
hunglp6d Jul 17, 2026
0486c58
fix(whatsapp): whitelist healthState before surfacing it
hunglp6d Jul 17, 2026
6c0dbe8
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 17, 2026
a4d7b16
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 17, 2026
9aba17d
fix(messaging): fail closed on unreachable WhatsApp status
apurvvkumaria Jul 17, 2026
bac2877
docs(messaging): clarify OpenClaw-only health probes
apurvvkumaria Jul 17, 2026
78303e1
fix(messaging): bound unconfigured WhatsApp probe
apurvvkumaria Jul 17, 2026
c57636f
merge(ci): refresh protected E2E interface
apurvvkumaria Jul 18, 2026
ec87c87
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cv Jul 18, 2026
d82c9f3
fix(whatsapp): report runtime pairing evidence
cv Jul 18, 2026
7a9a67a
merge(main): refresh PR 7015
cv Jul 18, 2026
769f314
fix(whatsapp): honor unreachable gateway status
cv Jul 18, 2026
5f375d7
Merge remote-tracking branch 'origin/main' into codex/salvage-7015-pa…
cv Jul 18, 2026
1e80552
test(e2e): reject unrelated rate-limit skips
cv Jul 18, 2026
0dd0e6f
merge: refresh PR #7015 from main
cv Jul 18, 2026
c4af726
fix(sandbox): retry pinned Hermes preflight reads
cv Jul 18, 2026
e8263bf
Merge remote-tracking branch 'origin/main' into codex/salvage-7015-pa…
cv Jul 19, 2026
638cd28
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cv Jul 19, 2026
b02c964
fix(messaging): validate WhatsApp status contract
apurvvkumaria Jul 19, 2026
3e324bd
fix(messaging): accept live WhatsApp status payload
apurvvkumaria Jul 19, 2026
dfcf933
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cv Jul 19, 2026
33c6f2f
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cv Jul 19, 2026
c7278e5
fix(messaging): fail closed on WhatsApp probe errors
cv Jul 19, 2026
6c04f8f
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cv Jul 19, 2026
ebfb80b
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cv Jul 19, 2026
e0100d4
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cv Jul 19, 2026
046e987
fix(messaging): consume WhatsApp account status
apurvvkumaria Jul 20, 2026
d68b395
fix(messaging): fail closed on summary-only status
apurvvkumaria Jul 20, 2026
62c5f84
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cjagwani Jul 20, 2026
2560dd6
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
cjagwani Jul 20, 2026
8b4e51f
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 20, 2026
b6d0ae1
Merge branch 'main' into fix/whatsapp-status-probe-unpaired
hunglp6d Jul 20, 2026
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
11 changes: 7 additions & 4 deletions docs/reference/commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1938,12 +1938,13 @@ $$nemoclaw my-assistant channels start telegram

Run messaging channel status checks.
Without `--channel`, the command prints a compact summary for every configured channel, including registration, policy coverage, and non-secret rendered config comparisons.
For channels that support a live health probe (WhatsApp, Telegram), the summary adds a `Runtime health: not checked in summary view` pointer instead of running the probe, so it never reads as healthy without an explicit check.
For channel and agent combinations that support a live health probe (WhatsApp or Telegram on OpenClaw), the summary adds a `Runtime health: not checked in summary view` pointer instead of running the probe, so it never reads as healthy without an explicit check.
With `--channel`, it prints the detailed status for that channel.

For WhatsApp, `--channel whatsapp` also probes the sandbox to separately report pairing/session state, the Noise WebSocket connection, inbound event delivery, and policy coverage.
For an OpenClaw WhatsApp sandbox, `--channel whatsapp` also probes the sandbox to separately report pairing/session state, the Noise WebSocket connection, inbound event delivery, and policy coverage.
A paired channel with no observed inbound delivery exits non-zero with verdict `idle` so an unhealthy bridge cannot pass as healthy.
The detailed WhatsApp probe stays focused on QR/session runtime diagnostics and does not include rendered-config comparison lines.
A Hermes WhatsApp sandbox uses the basic registration, policy, and config report because NemoClaw does not treat the Hermes session file as a live-health signal.

For Telegram, `--channel telegram` probes the sandbox to report the gateway process, Bot API reachability, and inbound delivery alongside the config comparison, and classifies the current state into a verdict such as `healthy`, `idle`, `unreachable` (network or egress), `token_rejected`, or `not_started`.
It reads the gateway's own startup and poll log breadcrumbs rather than issuing its own Bot API request, so the resolved bot token never leaves the gateway.
Expand All @@ -1964,9 +1965,11 @@ $$nemoclaw my-assistant channels status --channel telegram
| Flag | Description |
|------|-------------|
| `--channel <channel>` | Channel to inspect in detail |
| `--json` | Emit the status report as JSON (for the detailed WhatsApp and Telegram probes, exit non-zero when the verdict is not `healthy` or `unknown`) |
| `--json` | Emit the status report as JSON (for an available detailed WhatsApp or Telegram probe on OpenClaw, exit non-zero when the verdict is not `healthy` or `unknown`) |

Each probe is bounded by an in-sandbox `openshell sandbox exec` with a hard timeout and returns only matched bridge/gateway log lines (e.g. `connection.open`, `401 unauthorized`, `qr expired`, or `[telegram]` startup breadcrumbs) to the host, where NemoClaw reduces them to fixed classifications; the raw lines are never rendered, so the diagnostic output carries only those classifications, never message bodies or tokens.
Each live probe is bounded by an in-sandbox `openshell sandbox exec` with a hard timeout.
The WhatsApp probe returns strict OpenClaw status JSON to the host, where NemoClaw allowlists pairing, liveness, connection-state, and timestamp fields before rendering the report and discards phone-number and free-text error fields.
The Telegram probe returns only matched gateway log lines to the host, where NemoClaw reduces them to fixed classifications without rendering the raw lines, message bodies, or tokens.

</AgentOnly>

Expand Down
29 changes: 28 additions & 1 deletion scripts/managed-gateway-control.py
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,28 @@ def _recapture_exact_identity(
return current


def _read_stable_file_with_proof_grace(
reader: ProcReader,
identity: ProcessIdentity,
name: str,
limit: int,
) -> bytes:
"""Retry an inconsistent proc read only while the pinned process is exact."""

deadline = time.monotonic() + PROCESS_PROOF_GRACE_SECONDS
while True:
try:
return reader.read_stable_file(identity, name, limit)
except ControlError as error:
if error.code != "SUPERVISOR_UNAVAILABLE":
raise
_recapture_exact_identity(reader, identity, deadline=deadline)
remaining = deadline - time.monotonic()
if remaining <= 0:
raise
time.sleep(min(PROCESS_PROOF_RETRY_SECONDS, remaining))


def _basename(value: bytes) -> bytes:
return value.rsplit(b"/", 1)[-1]

Expand Down Expand Up @@ -1313,7 +1335,12 @@ def _hermes_preflight(reader: ProcReader, supervisor: ProcessIdentity) -> None:
validator,
["env-file", _system_path("/sandbox/.hermes/.env")],
)
raw_environment = reader.read_stable_file(supervisor, "environ", MAX_ENV_BYTES)
raw_environment = _read_stable_file_with_proof_grace(
reader,
supervisor,
"environ",
MAX_ENV_BYTES,
)
_validate_runtime_environment(validator, _parse_environment(raw_environment))
_verify_locked_hermes_hash()

Expand Down
2 changes: 1 addition & 1 deletion src/lib/actions/sandbox/channel-status-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import {
getBuiltInRenderedConfigParser,
tryGetMessagingAgentId,
} from "../../messaging";
import type { DiagnosticSignal } from "../../messaging/channels/channel-health";
import type {
ChannelConfigInputSpec,
MessagingAgentId,
MessagingSerializableValue,
SandboxMessagingInputReference,
} from "../../messaging/manifest";
import type { DiagnosticSignal } from "../../sandbox/whatsapp-diagnostics";
import * as registry from "../../state/registry";
import {
booleanConfigValue,
Expand Down
Loading
Loading