Skip to content

fix(telegram): read model from sandbox registry instead of hardcoding#379

Open
futhgar wants to merge 5 commits intoNVIDIA:mainfrom
futhgar:fix/telegram-bridge-hardcoded-model
Open

fix(telegram): read model from sandbox registry instead of hardcoding#379
futhgar wants to merge 5 commits intoNVIDIA:mainfrom
futhgar:fix/telegram-bridge-hardcoded-model

Conversation

@futhgar
Copy link
Copy Markdown

@futhgar futhgar commented Mar 19, 2026

Summary

The Telegram bridge banner always displays nvidia/nemotron-3-super-120b-a12b regardless of the actual configured inference provider. Users running Ollama, vLLM, or any non-default provider see a misleading model identity in the bridge startup output.

Fix

Read the model from the host-side sandbox registry (~/.nemoclaw/sandboxes.json) which nemoclaw onboard populates with the actual provider and model selection. Fall back to the default model only if the registry entry is missing.

Changes

File Change
scripts/telegram-bridge.js Import registry, look up sandbox by name, use sandboxInfo.model in banner
test/telegram-bridge-banner.test.js Regression test: verify banner uses registry lookup and has no hardcoded model string

Test plan

  • Banner formatting matches original width (56 chars) for all model lengths
  • npm test — 14/14 related tests pass (registry + banner + CLI)
  • Regression test verifies the banner line uses a variable, not a literal model string

Fixes #24

Summary by CodeRabbit

  • Bug Fixes

    • Startup banner and /start welcome message now display the configured provider and model (formatted/truncated), falling back to sensible defaults only when no configuration is present instead of a fixed model string.
  • Tests

    • Added tests to verify banner and /start outputs reflect configured provider/model and no longer include the old hard-coded model.

Signed-off-by: Josue Balandrano Coronel josuebc@pm.me

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

The telegram bridge now queries registry.getSandbox(SANDBOX) at runtime and uses the returned provider and model (with defaults if missing) to populate the startup console banner and the /start response. A new test suite verifies registry usage and absence of the hardcoded Nemotron string.

Changes

Cohort / File(s) Summary
Banner Script Update
scripts/telegram-bridge.js
Import ../bin/lib/registry; replace hard-coded provider/model strings in the startup console banner and the /start handler by calling registry.getSandbox(SANDBOX) and using info.provider / info.model with fallbacks (nvidia-nim, nvidia/nemotron-3-super-120b-a12b).
Banner Test Suite
test/telegram-bridge-banner.test.js
Add tests that assert telegram-bridge.js requires the registry and calls getSandbox, check source /start block lacks hardcoded Nemotron text and references provider, and run behavioral tests by creating a temporary sandbox JSON to ensure reported MODEL/PROVIDER come from the registry (not the hardcoded nemotron).

Sequence Diagram(s)

sequenceDiagram
    participant User as Telegram User
    participant Bridge as telegram-bridge.js
    participant Registry as bin/lib/registry
    participant Console as Startup Console

    User->>Bridge: sends /start
    Bridge->>Registry: getSandbox(SANDBOX)
    Registry-->>Bridge: { provider, model }
    Bridge->>Console: build banner using provider/model
    Bridge-->>User: send welcome message with provider/model
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through scripts and read the sand,

The banner now speaks the chosen brand.
No more baked-in Nemotron tale,
The registry's truth will now prevail.
🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: reading model from sandbox registry instead of hardcoding it, which is the primary objective of this PR.
Linked Issues check ✅ Passed The PR comprehensively addresses all coding requirements from issue #24: registry reads provider/model for both banner and /start response, fallback defaults implemented, and tests cover non-default provider scenarios.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the issue: updates to telegram-bridge.js for dynamic provider/model output and new test file for regression coverage. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@test/telegram-bridge-banner.test.js`:
- Around line 11-31: Add a behavioral test that mocks the registry lookup to
return a non-default model (e.g., "ollama/llama3"), executes the telegram-bridge
script, and asserts the rendered "Model:" banner line contains that model;
specifically, stub the module imported by telegram-bridge (the one matched by
require(...registry...)) so its getSandbox returns "ollama/llama3", then
re-require or invoke the banner generation and reuse the existing bannerLines
extraction to assert one of those lines includes "ollama/llama3" rather than the
default model.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e402916-45e0-4e4f-b8b3-2329b905dcc7

📥 Commits

Reviewing files that changed from the base of the PR and between 9513eca and 94e7d2a.

📒 Files selected for processing (2)
  • scripts/telegram-bridge.js
  • test/telegram-bridge-banner.test.js

@wscurran wscurran added bug Something isn't working Integration: Telegram Use this label to identify Telegram bot integration issues with NemoClaw. labels Mar 19, 2026
@kjw3
Copy link
Copy Markdown
Contributor

kjw3 commented Mar 19, 2026

This is a good narrow improvement, but I don’t think it fully closes #24 yet.

The banner model line now reads from the sandbox registry, which fixes part of the hardcoded
identity problem. But the Telegram bridge still reports a hardcoded Nemotron identity in the /
start message, and the change still does not surface the active provider. Because of that, the
user-visible model/provider identity is still inconsistent.

Concretely:

  • scripts/telegram-bridge.js still hardcodes Nemotron 3 Super 120B in the /start response
  • the PR updates the banner model line, but not the provider identity
  • the new test covers the banner model lookup path, but not the remaining hardcoded /start text

I’d be happy to re-review if you extend this so the Telegram bridge consistently reflects the
configured provider and model across all user-facing output.

@futhgar
Copy link
Copy Markdown
Author

futhgar commented Mar 20, 2026

Thanks @kjw3 — good catch. Pushed 886e2db which:

  • Reads both provider and model from the sandbox registry for the /start response (was hardcoded "Nemotron 3 Super 120B")
  • Adds a Provider: line to the startup banner
  • All user-facing output now consistently reflects the configured provider and model

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/telegram-bridge-banner.test.js (1)

37-39: Make temp-dir cleanup unconditional.

If assertions fail before Line 97/181, temporary directories are left behind. Use try/finally (or node:test teardown hooks) so cleanup always runs.

Minimal pattern
- const tmp = fs.mkdtempSync(...);
- ...
- fs.rmSync(tmp, { recursive: true, force: true });
+ const tmp = fs.mkdtempSync(...);
+ try {
+   ...
+ } finally {
+   fs.rmSync(tmp, { recursive: true, force: true });
+ }

Also applies to: 96-98, 131-133, 181-181

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

In `@test/telegram-bridge-banner.test.js` around lines 37 - 39, Wrap the
temporary-directory setup and usage (the tmp created by fs.mkdtempSync and
registryDir) in a try/finally so cleanup always runs even if assertions fail:
move fs.mkdtempSync(path.join(os.tmpdir(), "...")) and fs.mkdirSync(registryDir,
{ recursive: true }) into the test scope, run the test logic in the try block,
and call fs.rmSync(tmp, { recursive: true, force: true }) (or appropriate
rmdir/cleanup) in the finally; apply the same pattern to the other temp-dir
occurrences around the blocks creating tmp/registryDir so all temporary dirs are
removed unconditionally.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/telegram-bridge-banner.test.js`:
- Around line 63-94: The test currently reconstructs the banner via a node "-e"
inline snippet (uses spawnSync and registry.getSandbox) instead of running the
real bridge output, so update the test to invoke the actual bridge code: replace
the spawnSync invocation that passes "-e" and inline code with a spawnSync call
that executes the real script (e.g., "node scripts/telegram-bridge.js") or
require and call the bridge's exported function (if available) so the assertions
exercise the true output; make the same change for the second occurrence that
mirrors this pattern.

---

Nitpick comments:
In `@test/telegram-bridge-banner.test.js`:
- Around line 37-39: Wrap the temporary-directory setup and usage (the tmp
created by fs.mkdtempSync and registryDir) in a try/finally so cleanup always
runs even if assertions fail: move fs.mkdtempSync(path.join(os.tmpdir(), "..."))
and fs.mkdirSync(registryDir, { recursive: true }) into the test scope, run the
test logic in the try block, and call fs.rmSync(tmp, { recursive: true, force:
true }) (or appropriate rmdir/cleanup) in the finally; apply the same pattern to
the other temp-dir occurrences around the blocks creating tmp/registryDir so all
temporary dirs are removed unconditionally.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fd147081-87c6-431f-8744-863446d246be

📥 Commits

Reviewing files that changed from the base of the PR and between 886e2db and 4f8027c.

📒 Files selected for processing (1)
  • test/telegram-bridge-banner.test.js

@futhgar
Copy link
Copy Markdown
Author

futhgar commented Mar 29, 2026

@coderabbitai resume

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 29, 2026

✅ Actions performed

Reviews resumed.

futhgar added 5 commits April 1, 2026 02:11
The Telegram bridge banner always showed "nvidia/nemotron-3-super-120b-a12b"
regardless of the actual configured inference provider. Users running
Ollama or other providers saw a misleading model identity.

Read the model from the host-side sandbox registry (~/.nemoclaw/sandboxes.json)
which is populated by nemoclaw onboard with the actual provider and model
selection. Fall back to the default model only if the registry entry is missing.

Fixes NVIDIA#24

Signed-off-by: Josue Gomez <josue@guatulab.com>
Signed-off-by: futhgar <jmaldonado.rosa@gmail.com>
Address CodeRabbit review: add a test that sets up a registry with
a non-default model (ollama/llama3), runs the registry lookup with
HOME pointed at the temp dir, and verifies the banner output contains
the registry model instead of the hardcoded default.

Signed-off-by: Josue Gomez <josue@guatulab.com>
Signed-off-by: futhgar <jmaldonado.rosa@gmail.com>
…banner

Address kjw3 review: the /start Telegram response still hardcoded
"Nemotron 3 Super 120B". Now reads both model and provider from the
sandbox registry for both the /start message and the startup banner.
Consistent identity across all user-facing output.

Signed-off-by: Josue Gomez <josue@guatulab.com>
Signed-off-by: futhgar <jmaldonado.rosa@gmail.com>
Add structural test verifying the /start handler has no hardcoded model
string, and a behavioral test confirming it reflects configured provider
and model from the sandbox registry.

Signed-off-by: Josue Gomez <josue@guatulab.com>
Signed-off-by: futhgar <jmaldonado.rosa@gmail.com>
Address CodeRabbit review:
- Wrap all temp dir tests in try/finally for guaranteed cleanup
- Extract createTestRegistry() helper to reduce duplication
- Add comment explaining why tests use registry.getSandbox() directly
  rather than the full bridge script (requires Telegram token + openshell)

Signed-off-by: Josue Gomez <josue@guatulab.com>
Signed-off-by: futhgar <jmaldonado.rosa@gmail.com>
@futhgar futhgar force-pushed the fix/telegram-bridge-hardcoded-model branch from 65c5cd2 to bdd8fc5 Compare April 1, 2026 02:11
@futhgar
Copy link
Copy Markdown
Author

futhgar commented Apr 1, 2026

@kjw3 thanks for the review — your feedback was addressed in the follow-up commits (pushed shortly after your comment). The current state of the PR:

  1. /start response — now reads both model and provider from the sandbox registry (registry.getSandbox()), no more hardcoded Nemotron identity
  2. Banner — same fix, displays both provider and model from registry
  3. Tests — cover both the /start response and banner paths

Rebased onto main. Happy to adjust if anything else is needed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/telegram-bridge-banner.test.js (1)

4-9: Use ES module imports instead of CommonJS require().

The coding guidelines require ES modules for test files in test/. Convert these to ESM syntax.

♻️ Proposed fix
-const { describe, it } = require("node:test");
-const assert = require("node:assert/strict");
-const fs = require("node:fs");
-const os = require("node:os");
-const path = require("node:path");
-const { spawnSync } = require("node:child_process");
+import { describe, it } from "node:test";
+import assert from "node:assert/strict";
+import fs from "node:fs";
+import os from "node:os";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+import { spawnSync } from "node:child_process";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));

As per coding guidelines: test/**/*.test.js: Use ES modules (import/export) for test files in the test/ directory.

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

In `@test/telegram-bridge-banner.test.js` around lines 4 - 9, Replace the CommonJS
require() calls with ESM imports: change "const { describe, it } =
require('node:test')" to "import { describe, it } from 'node:test'", "const
assert = require('node:assert/strict')" to "import assert from
'node:assert/strict'", and similarly convert "fs", "os", "path" and "{ spawnSync
}" (from 'node:child_process') to ESM import statements; update any
destructuring usage to match the imported bindings (describe, it, assert, fs,
os, path, spawnSync) and ensure the test file is treated as an ES module by your
project config.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/telegram-bridge-banner.test.js`:
- Around line 4-9: Replace the CommonJS require() calls with ESM imports: change
"const { describe, it } = require('node:test')" to "import { describe, it } from
'node:test'", "const assert = require('node:assert/strict')" to "import assert
from 'node:assert/strict'", and similarly convert "fs", "os", "path" and "{
spawnSync }" (from 'node:child_process') to ESM import statements; update any
destructuring usage to match the imported bindings (describe, it, assert, fs,
os, path, spawnSync) and ensure the test file is treated as an ES module by your
project config.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4b86181a-ac81-4f00-a6be-723973b993ba

📥 Commits

Reviewing files that changed from the base of the PR and between 65c5cd2 and bdd8fc5.

📒 Files selected for processing (2)
  • scripts/telegram-bridge.js
  • test/telegram-bridge-banner.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/telegram-bridge.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Integration: Telegram Use this label to identify Telegram bot integration issues with NemoClaw.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix hardcoded model identity shown by the in-sandbox plugin/banner so it reflects the actual configured inference provider

3 participants