Skip to content

feat(onboard): support Telegram mention-only mode - #2417

Merged
cv merged 3 commits into
NVIDIA:mainfrom
latenighthackathon:fix/telegram-mention-only
May 1, 2026
Merged

feat(onboard): support Telegram mention-only mode#2417
cv merged 3 commits into
NVIDIA:mainfrom
latenighthackathon:fix/telegram-mention-only

Conversation

@latenighthackathon

@latenighthackathon latenighthackathon commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Parity with Discord's existing requireMention toggle, scoped to Telegram. Teams running the bot in busy Telegram groups can now restrict it to reply only when @mentioned instead of to every group message.

Problem

Telegram's group behavior in NemoClaw is hardcoded to groupPolicy: open — the bot answers every message the moment it joins a group. Users have no CLI flag, env var, or onboard prompt to narrow this; the only workaround is hand-patching openclaw.json after build.

Discord already has the equivalent via requireMention.

Changes

  • src/lib/sandbox-channels.ts — add requireMentionEnvKey: \"TELEGRAM_REQUIRE_MENTION\" + help string to the Telegram ChannelDef.
  • src/lib/onboard.ts — loosen the interactive mention-prompt gate: the prompt used to require both requireMentionEnvKey AND a populated serverIdEnvKey (Discord-specific). Now any channel with requireMentionEnvKey fires the prompt, with the Discord-specific server-ID check preserved. Also build a telegramConfig from TELEGRAM_REQUIRE_MENTION and pass it through patchStagedDockerfile.
  • Dockerfile — add ARG NEMOCLAW_TELEGRAM_CONFIG_B64=e30=, promote to ENV, and wire into the Python openclaw.json generator: ``groupPolicy`` becomes ``mentions`` when ``requireMention`` is truthy, otherwise ``open`` (existing default preserved).

Usage

Interactive:

[5/8] Messaging channels
...
✓ telegram token saved
Reply only when @mentioned? [Y/n]

Non-interactive:

TELEGRAM_REQUIRE_MENTION=1 nemoclaw onboard --non-interactive

Unset env + non-interactive = same as before (open groups). No behavior change for existing scripted onboards.

Test plan

Prior art

Closed PR #1784 by @kagura-agent proposed the same approach and was thanked by @wscurran with CodeRabbit review addressed before the author voluntarily closed "to reduce PR volume." This PR takes the same shape with a refreshed test layout and an explicit backward-compat regression test.

Fixes #1737.

Signed-off-by: latenighthackathon latenighthackathon@users.noreply.github.com

Summary by CodeRabbit

  • New Features

    • Configurable Telegram "mention-only" mode added as a build/runtime input and passed into the running environment.
    • Container now accepts an encoded Telegram config and uses it to set the channel policy instead of a fixed default.
    • Onboarding records Telegram mention preference, triggers sandbox recreation when it changes, and channel setup prompts respect mention-only controls.
  • Tests

    • Added unit tests for config injection, session persistence, validation, and compatibility.

@copy-pr-bot

copy-pr-bot Bot commented Apr 24, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Telegram mention-only configuration: onboarding captures/persists telegramConfig.requireMention, session schema and validation updated, Dockerfile accepts a base64 NEMOCLAW_TELEGRAM_CONFIG_B64 arg/env injected by the patcher, and build-time Python decodes it to set Telegram groupPolicy to mentions or open.

Changes

Cohort / File(s) Summary
Docker build
Dockerfile
Add ARG NEMOCLAW_TELEGRAM_CONFIG_B64=e30= and ENV NEMOCLAW_TELEGRAM_CONFIG_B64=${NEMOCLAW_TELEGRAM_CONFIG_B64}; build-time Python decodes this base64 JSON and sets Telegram groupPolicy to 'mentions' if requireMention:true, otherwise 'open'.
Onboarding core
src/lib/onboard.ts
Introduce computeTelegramRequireMention(), thread telegramConfig through createSandbox and patchStagedDockerfile(..., telegramConfig), persist onboardSession.telegramConfig, prompt for require-mention where channel exposes requireMentionEnvKey, and trigger sandbox recreation on require-mention drift.
Channel metadata
src/lib/sandbox-channels.ts
Add Telegram channel metadata fields: requireMentionEnvKey (TELEGRAM_REQUIRE_MENTION) and requireMentionHelp.
Session model / persistence
src/lib/onboard-session.ts
Add exported TelegramConfig type; add `telegramConfig: TelegramConfig
Unit tests
test/onboard.test.ts, src/lib/onboard-session.test.ts
Add tests for Dockerfile base64 injection/preservation for {requireMention:true}, {requireMention:false}, and empty config; extend session tests for save/load, normalization, corrupt-data handling, and safe-update behavior for telegramConfig.

Sequence Diagram

sequenceDiagram
    autonumber
    participant Env as Environment (env/CLI)
    participant Onboard as Onboard Service
    participant Patcher as Dockerfile Patcher
    participant Docker as Docker Build
    participant BuildPy as Build-time Python

    Env->>Onboard: TELEGRAM_REQUIRE_MENTION input
    Onboard->>Onboard: derive telegramConfig.requireMention
    Onboard->>Patcher: patchStagedDockerfile(..., telegramConfig)
    Patcher->>Patcher: JSON -> base64 (NEMOCLAW_TELEGRAM_CONFIG_B64)
    Patcher->>Docker: start image build (ARG/ENV passed)
    Docker->>BuildPy: run inline Python with NEMOCLAW_TELEGRAM_CONFIG_B64
    BuildPy->>BuildPy: base64-decode JSON
    BuildPy->>BuildPy: set Telegram groupPolicy = "mentions" or "open"
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibble a key in base64 bright,

tuck mention rules into the night.
If folks must ping before I leap,
I’ll hush the group and softly keep.
Hopping code, I guard the chat.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(onboard): support Telegram mention-only mode' accurately reflects the main change: adding Telegram mention-only mode support to the onboarding flow.
Linked Issues check ✅ Passed All coding requirements from issue #1737 are met: interactive prompt support, non-interactive env var (TELEGRAM_REQUIRE_MENTION), Dockerfile configuration with base64-encoded config, session persistence, and backward compatibility with default 'open' behavior.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing Telegram mention-only mode: Dockerfile arg/env handling, onboard.ts configuration logic, sandbox-channels.ts metadata, and comprehensive test coverage. No unrelated modifications detected.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@latenighthackathon latenighthackathon changed the title feat(onboard): support Telegram mention-only mode (fixes #1737) feat(onboard): support Telegram mention-only mode Apr 24, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/onboard.ts`:
- Around line 3823-3832: The Telegram reply-mode flag (TELEGRAM_REQUIRE_MENTION)
is only read into telegramConfig during Dockerfile rebuilds, so changes are
ignored when a sandbox is reused; update the reuse/path logic to consider
TELEGRAM_REQUIRE_MENTION drift by persisting the effective Telegram config (from
telegramConfig) into the sandbox registry or session state and comparing it
during reuse checks, and if it differs from the incoming env value (or desired
groupPolicy), trigger the same rebuild/warning/force-recreate flow as the
Dockerfile change path; specifically, modify the reuse handling code that checks
enabledTokenEnvKeys and groupPolicy to load and compare the saved Telegram
config entry and enforce rebuild or surface a user-facing warning when
TELEGRAM_REQUIRE_MENTION semantics change.

In `@src/lib/sandbox-channels.ts`:
- Around line 35-37: Update the requireMentionHelp string (paired with
requireMentionEnvKey) so it no longer states that DMs are always answered;
clarify that this setting only controls group-chat behavior and note that direct
messages may still be restricted by pairing or TELEGRAM_ALLOWED_IDS (or other
access controls). Locate the requireMentionHelp constant in
src/lib/sandbox-channels.ts and replace the overpromising help text with a
concise description that explicitly limits the scope to group chats and mentions
the potential DM restrictions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 10d86093-2cf8-4419-a74a-884bc6567157

📥 Commits

Reviewing files that changed from the base of the PR and between 99b72c4 and ac6731f.

📒 Files selected for processing (4)
  • Dockerfile
  • src/lib/onboard.ts
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts

Comment thread src/lib/onboard.ts
Comment thread src/lib/sandbox-channels.ts Outdated
@latenighthackathon
latenighthackathon force-pushed the fix/telegram-mention-only branch from ac6731f to 871b21e Compare April 24, 2026 06:03
@latenighthackathon

latenighthackathon commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed both CodeRabbit nits in 871b21e4.

Cheers!

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/onboard-session.test.ts`:
- Around line 166-173: The test currently calls session.saveSession which
normalizes telegramConfig, so to exercise rejection-on-load you must persist a
malformed session payload directly (or mock the session read) and then call
session.loadSession to assert it throws; specifically, create the session with
session.createSession(), construct a malformed telegramConfig (e.g.,
requireMention: "yes"), write that malformed JSON into the session persistence
backend for that session id (or stub the session file reader method such as the
internal read/load helper), and then call session.loadSession(sessionId)
expecting it to reject or throw instead of using session.saveSession which
sanitizes input.

In `@src/lib/onboard-session.ts`:
- Line 103: filterSafeUpdates currently omits SessionUpdates.telegramConfig so
calls to markStepComplete() / completeSession() drop telegramConfig silently;
update filterSafeUpdates to preserve and copy the telegramConfig field when
present (and ensure its type matches TelegramConfig | null) so that
markStepComplete() and completeSession() propagate telegramConfig through safe
update paths instead of discarding it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: aa408aed-835a-4dbc-a9e6-f19c6629a940

📥 Commits

Reviewing files that changed from the base of the PR and between ac6731f and 871b21e.

📒 Files selected for processing (6)
  • Dockerfile
  • src/lib/onboard-session.test.ts
  • src/lib/onboard-session.ts
  • src/lib/onboard.ts
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts
✅ Files skipped from review due to trivial changes (2)
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/onboard.ts

Comment thread src/lib/onboard-session.test.ts
Comment thread src/lib/onboard-session.ts
@latenighthackathon
latenighthackathon force-pushed the fix/telegram-mention-only branch from 871b21e to 7ae976f Compare April 24, 2026 06:21
@latenighthackathon

latenighthackathon commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed both follow-up CodeRabbit nits in 7ae976f3.
Cheers!

@coderabbitai coderabbitai Bot left a comment

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.

♻️ Duplicate comments (1)
src/lib/onboard.ts (1)

3835-3859: ⚠️ Potential issue | 🟠 Major

Telegram mention-mode drift is still missed in reuse flows.

This session write only helps --resume; a normal nemoclaw onboard run creates a fresh session before createSandbox() decides whether to reuse, so an existing ready sandbox can still be reused with the old Telegram groupPolicy. And even on resume, telegramConfigChanged misses true -> unset, although the Dockerfile generator would switch that back to open. Please persist the effective Telegram mode somewhere the general reuse path can read it, and compare effective runtime policy (Boolean(requireMention)) rather than only non-null mismatches.

Also applies to: 6900-6934

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard.ts` around lines 3835 - 3859, The effective Telegram
mention-mode (computed via computeTelegramRequireMention and stored in
telegramConfig) is not persisted where the general sandbox reuse path
(createSandbox and the reuse decision) can read it, and the comparison logic
only checks non-null mismatches so it misses true->unset transitions; persist
the resolved Boolean(requireMention) into a shared place used by reuse (e.g.,
set onboardSession.telegramConfigEffective or the sandbox metadata that
createSandbox reads) whenever computeTelegramRequireMention runs, and update the
reuse/comparison logic (telegramConfigChanged or reuse decision) to compare the
effective runtime policy via Boolean(requireMention) rather than null/non-null
so both true->false and true->unset are detected and force sandbox recreate.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/lib/onboard.ts`:
- Around line 3835-3859: The effective Telegram mention-mode (computed via
computeTelegramRequireMention and stored in telegramConfig) is not persisted
where the general sandbox reuse path (createSandbox and the reuse decision) can
read it, and the comparison logic only checks non-null mismatches so it misses
true->unset transitions; persist the resolved Boolean(requireMention) into a
shared place used by reuse (e.g., set onboardSession.telegramConfigEffective or
the sandbox metadata that createSandbox reads) whenever
computeTelegramRequireMention runs, and update the reuse/comparison logic
(telegramConfigChanged or reuse decision) to compare the effective runtime
policy via Boolean(requireMention) rather than null/non-null so both true->false
and true->unset are detected and force sandbox recreate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 27fe17de-3553-4607-b44b-9f1af9687a29

📥 Commits

Reviewing files that changed from the base of the PR and between 871b21e and 7ae976f.

📒 Files selected for processing (6)
  • Dockerfile
  • src/lib/onboard-session.test.ts
  • src/lib/onboard-session.ts
  • src/lib/onboard.ts
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts
✅ Files skipped from review due to trivial changes (3)
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts
  • src/lib/onboard-session.test.ts

@latenighthackathon
latenighthackathon force-pushed the fix/telegram-mention-only branch from 7ae976f to 06b8f83 Compare April 25, 2026 05:08

@coderabbitai coderabbitai Bot left a comment

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.

♻️ Duplicate comments (1)
src/lib/onboard.ts (1)

4039-4052: ⚠️ Potential issue | 🟠 Major

Persist Telegram reply mode in sandbox metadata, not just the resume session.

Lines 4044-4051 only write this into onboardSession. A fresh nemoclaw onboard creates a new session before createSandbox() reaches its normal reuse branch, and that branch still does not compare any recorded Telegram mode, so changing TELEGRAM_REQUIRE_MENTION on an existing ready sandbox can still be ignored unless the user forces recreation. Please store the effective Telegram group policy with the sandbox’s persisted metadata and check it during the regular reuse flow, not only during --resume.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard.ts` around lines 4039 - 4052, The code only writes
telegramConfig.requireMention into onboardSession via
onboardSession.updateSession, but you must also persist the effective Telegram
group policy into the sandbox's persisted metadata so the normal createSandbox
reuse branch will detect drift; update the logic that writes
current.telegramConfig (where telegramConfig.requireMention is checked) to also
write the same value into the sandbox metadata object saved/updated during
sandbox creation/update (the code paths involved around createSandbox and the
sandbox reuse branch), and ensure the reuse flow compares the persisted sandbox
metadata's Telegram policy against the current TELEGRAM_REQUIRE_MENTION to
trigger sandbox recreation when they differ.
🧹 Nitpick comments (1)
src/lib/onboard-session.ts (1)

604-608: Prefer reusing parseTelegramConfig here to avoid validation drift.

filterSafeUpdates currently duplicates telegram parsing logic. Reusing the helper keeps one source of truth.

♻️ Proposed refactor
-  if (isObject(updates.telegramConfig) && typeof updates.telegramConfig.requireMention === "boolean") {
-    safe.telegramConfig = { requireMention: updates.telegramConfig.requireMention };
-  } else if (updates.telegramConfig === null) {
+  const parsedTelegram = parseTelegramConfig(updates.telegramConfig);
+  if (parsedTelegram) {
+    safe.telegramConfig = parsedTelegram;
+  } else if (updates.telegramConfig === null) {
     safe.telegramConfig = null;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard-session.ts` around lines 604 - 608, In filterSafeUpdates,
replace the inline telegram parsing with a call to the existing
parseTelegramConfig helper to avoid validation drift: when
updates.telegramConfig is provided, set safe.telegramConfig to null if
updates.telegramConfig === null, otherwise pass updates.telegramConfig into
parseTelegramConfig(...) and assign its result; ensure you only call
parseTelegramConfig when updates.telegramConfig is not undefined so behavior for
omitted fields remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/lib/onboard.ts`:
- Around line 4039-4052: The code only writes telegramConfig.requireMention into
onboardSession via onboardSession.updateSession, but you must also persist the
effective Telegram group policy into the sandbox's persisted metadata so the
normal createSandbox reuse branch will detect drift; update the logic that
writes current.telegramConfig (where telegramConfig.requireMention is checked)
to also write the same value into the sandbox metadata object saved/updated
during sandbox creation/update (the code paths involved around createSandbox and
the sandbox reuse branch), and ensure the reuse flow compares the persisted
sandbox metadata's Telegram policy against the current TELEGRAM_REQUIRE_MENTION
to trigger sandbox recreation when they differ.

---

Nitpick comments:
In `@src/lib/onboard-session.ts`:
- Around line 604-608: In filterSafeUpdates, replace the inline telegram parsing
with a call to the existing parseTelegramConfig helper to avoid validation
drift: when updates.telegramConfig is provided, set safe.telegramConfig to null
if updates.telegramConfig === null, otherwise pass updates.telegramConfig into
parseTelegramConfig(...) and assign its result; ensure you only call
parseTelegramConfig when updates.telegramConfig is not undefined so behavior for
omitted fields remains unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c5b456eb-b531-46c3-80b9-b22a33d1d2e9

📥 Commits

Reviewing files that changed from the base of the PR and between 7ae976f and 06b8f83.

📒 Files selected for processing (6)
  • Dockerfile
  • src/lib/onboard-session.test.ts
  • src/lib/onboard-session.ts
  • src/lib/onboard.ts
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts
✅ Files skipped from review due to trivial changes (1)
  • src/lib/sandbox-channels.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/lib/onboard-session.test.ts
  • Dockerfile
  • test/onboard.test.ts

@latenighthackathon
latenighthackathon force-pushed the fix/telegram-mention-only branch from 06b8f83 to b0d2e74 Compare April 26, 2026 18:50

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/lib/onboard.ts (1)

7604-7614: ⚠️ Potential issue | 🟠 Major

Compare the effective Telegram mode, not just non-null booleans.

This only flags drift when both sides are non-null. A sandbox previously built with Telegram's default-open behavior (recordedTelegramRequireMention === null) will still be reused unchanged when the user later sets TELEGRAM_REQUIRE_MENTION=1, and the reverse transition back to default-open is ignored too. That leaves groupPolicy stale after resume.

Proposed fix
-    const currentTelegramRequireMention = computeTelegramRequireMention();
-    const recordedTelegramRequireMention = session?.telegramConfig?.requireMention ?? null;
-    const telegramConfigChanged =
-      currentTelegramRequireMention !== null &&
-      recordedTelegramRequireMention !== null &&
-      currentTelegramRequireMention !== recordedTelegramRequireMention;
+    const currentTelegramRequireMention = computeTelegramRequireMention();
+    const recordedTelegramRequireMention = session?.telegramConfig?.requireMention ?? null;
+    const telegramEnabledPreviously = session?.messagingChannels?.includes("telegram") === true;
+    const effectiveCurrentTelegramRequireMention = telegramEnabledPreviously
+      ? (currentTelegramRequireMention ?? false)
+      : currentTelegramRequireMention;
+    const effectiveRecordedTelegramRequireMention = telegramEnabledPreviously
+      ? (recordedTelegramRequireMention ?? false)
+      : recordedTelegramRequireMention;
+    const telegramConfigChanged =
+      effectiveCurrentTelegramRequireMention !== effectiveRecordedTelegramRequireMention;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard.ts` around lines 7604 - 7614, The code only treats a change
as drift when both currentTelegramRequireMention and
recordedTelegramRequireMention are non-null, which misses transitions involving
the default/open mode (null). Update the logic around
computeTelegramRequireMention, recordedTelegramRequireMention and
telegramConfigChanged to compare the effective Telegram mode by normalizing
nulls to the same default value (use the same default semantics as
TELEGRAM_REQUIRE_MENTION/open mode) before comparing; i.e., derive
effectiveCurrent = computeTelegramRequireMention() ?? DEFAULT and
effectiveRecorded = session?.telegramConfig?.requireMention ?? DEFAULT and then
set telegramConfigChanged = effectiveCurrent !== effectiveRecorded so both
transitions to/from default are detected (this will keep groupPolicy in sync on
resume).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/onboard.ts`:
- Around line 332-336: The function computeTelegramRequireMention currently
returns null for any value other than "0" or "1", silently treating typos as
unset; update computeTelegramRequireMention to explicitly validate
process.env.TELEGRAM_REQUIRE_MENTION: return true for "1", false for "0", return
null only if the env var is undefined or empty, and throw a clear Error (or
raise a validation exception) if the value is present but not "0" or "1" so
invalid configs like "true" are rejected during startup.

---

Duplicate comments:
In `@src/lib/onboard.ts`:
- Around line 7604-7614: The code only treats a change as drift when both
currentTelegramRequireMention and recordedTelegramRequireMention are non-null,
which misses transitions involving the default/open mode (null). Update the
logic around computeTelegramRequireMention, recordedTelegramRequireMention and
telegramConfigChanged to compare the effective Telegram mode by normalizing
nulls to the same default value (use the same default semantics as
TELEGRAM_REQUIRE_MENTION/open mode) before comparing; i.e., derive
effectiveCurrent = computeTelegramRequireMention() ?? DEFAULT and
effectiveRecorded = session?.telegramConfig?.requireMention ?? DEFAULT and then
set telegramConfigChanged = effectiveCurrent !== effectiveRecorded so both
transitions to/from default are detected (this will keep groupPolicy in sync on
resume).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 36fa6f6b-294a-425c-82b1-4a2e73bc962e

📥 Commits

Reviewing files that changed from the base of the PR and between 06b8f83 and b0d2e74.

📒 Files selected for processing (6)
  • Dockerfile
  • src/lib/onboard-session.test.ts
  • src/lib/onboard-session.ts
  • src/lib/onboard.ts
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts
✅ Files skipped from review due to trivial changes (3)
  • src/lib/sandbox-channels.ts
  • test/onboard.test.ts
  • src/lib/onboard-session.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/onboard-session.test.ts
  • Dockerfile

Comment thread src/lib/onboard.ts
Comment on lines +332 to +336
function computeTelegramRequireMention(): boolean | null {
const raw = process.env.TELEGRAM_REQUIRE_MENTION;
if (raw === "1") return true;
if (raw === "0") return false;
return null;

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.

⚠️ Potential issue | 🟠 Major

Reject invalid TELEGRAM_REQUIRE_MENTION values instead of silently treating them as unset.

Any value other than "0" or "1" falls through to null, and the rest of the flow interprets that as default-open behavior. In non-interactive onboarding, a typo like TELEGRAM_REQUIRE_MENTION=true will quietly disable mention-only mode and make the bot reply to every group message.

Proposed fix
 function computeTelegramRequireMention(): boolean | null {
   const raw = process.env.TELEGRAM_REQUIRE_MENTION;
+  if (raw === undefined || raw === "") return null;
   if (raw === "1") return true;
   if (raw === "0") return false;
-  return null;
+  console.error("  TELEGRAM_REQUIRE_MENTION must be set to 0 or 1.");
+  process.exit(1);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard.ts` around lines 332 - 336, The function
computeTelegramRequireMention currently returns null for any value other than
"0" or "1", silently treating typos as unset; update
computeTelegramRequireMention to explicitly validate
process.env.TELEGRAM_REQUIRE_MENTION: return true for "1", false for "0", return
null only if the env var is undefined or empty, and throw a clear Error (or
raise a validation exception) if the value is present but not "0" or "1" so
invalid configs like "true" are rejected during startup.

@wscurran wscurran added NemoClaw CLI integration: telegram Telegram integration or channel behavior labels Apr 27, 2026
@wscurran

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this pull request that proposes a way to add support for Telegram mention-only mode, providing parity with Discord's existing requireMention toggle.


Related open issues:

1 similar comment
@wscurran

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this pull request that proposes a way to add support for Telegram mention-only mode, providing parity with Discord's existing requireMention toggle.


Related open issues:

@latenighthackathon
latenighthackathon force-pushed the fix/telegram-mention-only branch from b0d2e74 to 9aa3c3c Compare April 27, 2026 19:09
latenighthackathon added a commit to latenighthackathon/NemoClaw that referenced this pull request Apr 27, 2026
…rift

The drift check at the resume gate was guarded on
recordedTelegramRequireMention !== null && currentTelegramRequireMention !== null,
which only flagged a mismatch when both sides were boolean. Two real
sequences fell through:

- Sandbox built before TELEGRAM_REQUIRE_MENTION existed
  (recordedTelegramRequireMention === null), then user sets
  TELEGRAM_REQUIRE_MENTION=1. Drift unflagged → sandbox reused with
  baked-in groupPolicy: open even though user asked for mentions.
- Sandbox built with TELEGRAM_REQUIRE_MENTION=1 (recorded true), then
  user unsets the env var. Drift unflagged → sandbox reused with baked-in
  groupPolicy: mentions even though user expects default-open.

Collapse null and false to the same effective mode (default-open) before
comparing, so any change to the user-visible behavior triggers a recreate.
Mirrors the underlying rule in the openclaw.json generator: empty config
→ groupPolicy: open. Closes the CodeRabbit review item on NVIDIA#2417.

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
NemoClaw already offers Discord's `requireMention` toggle (reply only
when @mentioned vs to all messages in a guild), but Telegram's group
behavior is effectively fixed to `groupPolicy: open` — the bot replies
to every message in every group it joins. Teams running the bot in
busy Telegram groups have no way to restrict it to mentions without
hand-patching `openclaw.json` after build.

Parity with Discord's `requireMention`, scoped to Telegram:

- **`src/lib/sandbox-channels.ts`** — add `requireMentionEnvKey:
  "TELEGRAM_REQUIRE_MENTION"` plus a help string to the telegram
  `ChannelDef`. The help text explicitly scopes the setting to group
  chats and notes DMs stay subject to pairing / TELEGRAM_ALLOWED_IDS.
- **`src/lib/onboard.ts`** — loosen the interactive mention-prompt
  gate: the prompt used to require both a `requireMentionEnvKey` AND
  a configured `serverIdEnvKey` (Discord-specific). Telegram has no
  server ID, so the prompt never fired. Now it fires for any channel
  with `requireMentionEnvKey` whose `serverIdEnvKey` (if present) is
  populated — Telegram's prompt always fires, Discord's still gates
  on a configured server ID.
- **`src/lib/onboard.ts`** — new `computeTelegramRequireMention()`
  helper reads `TELEGRAM_REQUIRE_MENTION` (set either by the
  interactive prompt above or by a non-interactive env export) and
  maps it to `true | false | null`. Used both at build time to bake
  the `telegramConfig` into the Dockerfile and at resume time to
  detect drift.
- **`src/lib/onboard-session.ts`** — add `TelegramConfig` type +
  `telegramConfig: TelegramConfig | null` field on `Session` with a
  `parseTelegramConfig()` that rejects non-boolean values. Persisted
  in both `createSession` and `normalizeSession`.
- **`src/lib/onboard.ts`** — on every build, write the effective
  `telegramConfig` into session state via `onboardSession.updateSession`.
- **`src/lib/onboard.ts`** — reuse path computes
  `telegramConfigChanged` (current env vs recorded session) alongside
  `webSearchConfigChanged`. Drift triggers a `[resume] TELEGRAM_REQUIRE_MENTION
  changed; recreating sandbox.` note and forces a fresh build so the
  new `groupPolicy` actually takes effect — otherwise the config
  stays baked at the old value.
- **`Dockerfile`** — add `ARG NEMOCLAW_TELEGRAM_CONFIG_B64=e30=`,
  promote to ENV, and read it in the existing python3 openclaw.json
  generator. When `requireMention` is truthy, telegram's
  `groupPolicy` is set to `mentions`; otherwise `open` (existing
  default, preserved for backward compatibility).

Interactive: when a user enables Telegram in step [5/8] of onboard,
the wizard now asks "Reply only when @mentioned? [Y/n]" after the
token prompt.

Non-interactive:

    TELEGRAM_REQUIRE_MENTION=1 nemoclaw onboard --non-interactive

    # or
    TELEGRAM_REQUIRE_MENTION=0 nemoclaw onboard --non-interactive

Unset env var + non-interactive = same as before (open groups). No
behavior change for existing sandboxes or scripted onboards that
don't set the new variable.

If a user re-runs onboard against an existing sandbox with a
different TELEGRAM_REQUIRE_MENTION value, the resume path now
detects the drift and recreates the sandbox so the new group policy
actually takes effect — instead of silently keeping the stale value
baked into the old image.

- `npx vitest run test/onboard.test.ts` — 3 new end-to-end tests
  exercising `patchStagedDockerfile` with mention-only, open-group,
  and empty telegramConfig.
- `npx vitest run src/lib/onboard-session.test.ts` — 4 new tests
  covering telegramConfig save/load roundtrips (both boolean
  values), malformed input rejection, and null default on fresh
  sessions.
- Full onboard + onboard-selection + sandbox-channels suite: 208
  tests pass, no regressions.
- Typecheck clean.

Closed PR NVIDIA#1784 by @kagura-agent proposed the same interactive +
env-var approach and was thanked by @wscurran with CodeRabbit review
addressed before the author voluntarily closed to reduce PR volume.
This PR takes the same shape plus the drift-detection path that
CodeRabbit flagged on the resume case (sandbox reuse would
otherwise ignore changes to TELEGRAM_REQUIRE_MENTION until the user
forced a rebuild).

Discord's `requireMention` has the same pre-existing limitation on
the reuse path — changing DISCORD_REQUIRE_MENTION against a reused
sandbox keeps the old value. That's out of scope for this PR; a
follow-up would apply the same session-state-tracked drift pattern
to discordGuilds.

Fixes NVIDIA#1737.

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
…rift

The drift check at the resume gate was guarded on
recordedTelegramRequireMention !== null && currentTelegramRequireMention !== null,
which only flagged a mismatch when both sides were boolean. Two real
sequences fell through:

- Sandbox built before TELEGRAM_REQUIRE_MENTION existed
  (recordedTelegramRequireMention === null), then user sets
  TELEGRAM_REQUIRE_MENTION=1. Drift unflagged → sandbox reused with
  baked-in groupPolicy: open even though user asked for mentions.
- Sandbox built with TELEGRAM_REQUIRE_MENTION=1 (recorded true), then
  user unsets the env var. Drift unflagged → sandbox reused with baked-in
  groupPolicy: mentions even though user expects default-open.

Collapse null and false to the same effective mode (default-open) before
comparing, so any change to the user-visible behavior triggers a recreate.
Mirrors the underlying rule in the openclaw.json generator: empty config
→ groupPolicy: open. Closes the CodeRabbit review item on NVIDIA#2417.

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
@latenighthackathon
latenighthackathon force-pushed the fix/telegram-mention-only branch from 60ab29a to 8be1cd3 Compare April 29, 2026 08:00
@latenighthackathon

latenighthackathon commented Apr 29, 2026

Copy link
Copy Markdown
Collaborator Author

Rebased onto current upstream/main (b4df07ea) - Cheers!

@cjagwani cjagwani self-assigned this May 1, 2026
@cjagwani

cjagwani commented May 1, 2026

Copy link
Copy Markdown
Collaborator

verified end-to-end:

• python generator (the layer not covered by PR tests) — ran build_config()
with 6 inputs: requireMention=true/false, env unset, empty {}, null,
truthy-string. all 6 produce the correct groupPolicy ("mentions" vs "open").
backward compat preserved.

• upstream layers — author's tests cover persistence (7 cases on
telegramConfig save/load + malformed rejection), filterSafeUpdates routing,
and onboard env→Dockerfile-arg wiring.

ready to merge.

@cv
cv merged commit c7e49ad into NVIDIA:main May 1, 2026
10 of 11 checks passed
cv pushed a commit that referenced this pull request May 2, 2026
## Summary
Daily release-prep documentation refresh for merged PRs from the past 24
hours.
This updates user-facing docs for Telegram mention-only mode, in-sandbox
messaging shutdown, Hermes onboarding/runtime behavior, and
compatible-endpoint smoke validation, then bumps the docs metadata to
0.0.33 after tag v0.0.32.

## Related Issue
None.

## Changes
- #2417 / c7e49ad: Document `TELEGRAM_REQUIRE_MENTION` for Telegram
group-chat replies in `docs/manage-sandboxes/messaging-channels.md` and
`docs/reference/commands.md`.
- #1977 / 69403e0: Update `nemoclaw tunnel stop` and deprecated
`nemoclaw stop` docs to explain that NemoClaw also attempts to stop the
in-sandbox OpenClaw gateway and messaging polling.
- #2781 / b83ffe2, #2859 / 4df8be6, and #2846 / 0968dfd: Refresh the
Hermes quickstart for the default `my-hermes` sandbox name, cross-agent
same-name guard, agent type visibility in `nemoclaw list`, Brave prompt
omission, and supported prebaked Hermes integrations.
- #2849 / fd240ff: Document the Telegram plus OpenAI-compatible
endpoint `inference.local` smoke check in inference options and
troubleshooting.
- Bump `docs/versions1.json` and `docs/project.json` from 0.0.32 to
0.0.33 for daily release preparation.

## Type of Change
- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [x] Doc only (includes code sample changes)

## Verification
- [ ] `npx prek run --all-files` passes
- [ ] `npm test` passes
- [ ] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [x] Docs updated for user-facing behavior changes
- [x] `make docs` builds without warnings (doc changes only)
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

Additional checks run:
- `python3 scripts/docs-to-skills.py docs/ .agents/skills/ --prefix
nemoclaw-user --dry-run`
- `git diff --check`
- `make docs` passed with the existing local version-switcher read
message.
- Full `npx prek run --all-files` and `npm test` were skipped for this
doc-only automation run. Commit and pre-push hooks otherwise passed
docs, lint, secret, and conversion checks until the local `Test (skills
YAML)` hook failed because `vitest/config` is not installed in this
fresh worktree.

---
Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Updated Hermes quickstart: default sandbox name is "hermes"; guidance
to use distinct sandbox names, note same-name reuse is prevented, Hermes
wizard does not request Brave Web Search, and sandbox listings now show
agent type.
* Clarified provider onboarding: bounded in-sandbox smoke check runs
when Telegram messaging is enabled.
* Expanded Telegram docs: added TELEGRAM_REQUIRE_MENTION (DMs still
governed by TELEGRAM_ALLOWED_IDS), onboarding examples,
stop-messaging/tunnel behavior, and troubleshooting.
  * Promoted docs to version 0.0.33.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Miyoung Choi <miyoungc@nvidia.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
senthilr-nv added a commit to senthilr-nv/NemoClaw that referenced this pull request May 5, 2026
…licy enum

The config generator emitted groupPolicy: "mentions" when
TELEGRAM_REQUIRE_MENTION=1, but the OpenClaw gateway schema only
accepts "open", "disabled", or "allowlist" — crashing the gateway
on startup (introduced by NVIDIA#2417).

The correct approach per OpenClaw docs is to keep groupPolicy: "open"
(groups remain accessible) and set per-group mention-gating via
groups: { "*": { requireMention: true } }. The previous "mentions"
value conflated two independent controls.

Fixes NVIDIA#3022

Signed-off-by: Senthil Ravichandran <senthilr@nvidia.com>
@latenighthackathon
latenighthackathon deleted the fix/telegram-mention-only branch May 18, 2026 05:11
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output feature PR adds or expands user-visible functionality and removed NemoClaw CLI labels Jun 3, 2026
@wscurran wscurran added the NV QA Bugs found by the NVIDIA QA Team label Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output feature PR adds or expands user-visible functionality integration: telegram Telegram integration or channel behavior NV QA Bugs found by the NVIDIA QA Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[all platform]support Telegram mention-only mode in NemoClaw onboarding/config (parity with Discord requireMention)

4 participants