fix(plugin): always probe live gateway model for TUI footer - #2661
Conversation
After a runtime `openshell inference set` the plugin was reading the inference model only from the on-disk onboard config, which is never updated at runtime, so the TUI footer showed a stale onboard-time model. Fix: always call probeOpenShellInference() at plugin registration and prefer its result for the banner and registered provider model so the footer reflects the live gateway state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Jason Ma <jama@nvidia.com>
📝 WalkthroughWalkthroughModel selection and provider registration now always probe the live OpenShell gateway and prefer the probed gateway model for active/banners, rather than relying on onboard configuration; activeModel defaults to an empty string when neither source provides a model. Changes
Sequence Diagram(s)sequenceDiagram
participant Register as Register()
participant Probe as probeOpenShellInference()
participant Provider as Provider Registry
participant TUI as OpenClaw TUI / Banner
Register->>Probe: probeOpenShellInference()
Note right of Probe: returns probed.model, endpoint, provider
Probe-->>Register: probed result
Register->>Provider: register provider using probed.model
Provider-->>Register: registration confirmation
Register->>TUI: compute bannerModel (prefer probed.model) and banner endpoint/provider
TUI-->>Register: render footer with live probed model
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 8/10 reviews remaining, refill in 11 minutes and 20 seconds. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
nemoclaw/src/index.ts (1)
334-353: Don't block plugin registration on the live probe.
execFileSync("openshell", ...)now runs on every plugin load, so a slow or missing CLI can stall startup synchronously before the TUI appears. Consider caching the last known live model or refreshing it after registration instead of on the hot path.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nemoclaw/src/index.ts` around lines 334 - 353, The code currently calls probeOpenShellInference() synchronously on the hot path which can block startup; change registration to use the onboard config as the immediate source and defer or async-refresh the live probe: call loadOnboardConfig() and compute bannerEndpoint/bannerProvider/bannerModel from onboardCfg only (use onboardCfg?.model or defaults) and call api.registerProvider(registeredProviderForConfig(onboardCfg, providerCredentialEnv, /*model*/ onboardCfg?.model ?? undefined)) immediately; then invoke probeOpenShellInference() off the main path (spawn a Promise/worker) and when it resolves, recompute the provider info and re-register or update the provider via api.registerProvider(registeredProviderForConfig(..., probed.model)) so the probe no longer blocks the TUI startup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@nemoclaw/src/index.ts`:
- Around line 334-353: The code currently calls probeOpenShellInference()
synchronously on the hot path which can block startup; change registration to
use the onboard config as the immediate source and defer or async-refresh the
live probe: call loadOnboardConfig() and compute
bannerEndpoint/bannerProvider/bannerModel from onboardCfg only (use
onboardCfg?.model or defaults) and call
api.registerProvider(registeredProviderForConfig(onboardCfg,
providerCredentialEnv, /*model*/ onboardCfg?.model ?? undefined)) immediately;
then invoke probeOpenShellInference() off the main path (spawn a Promise/worker)
and when it resolves, recompute the provider info and re-register or update the
provider via api.registerProvider(registeredProviderForConfig(...,
probed.model)) so the probe no longer blocks the TUI startup.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: b1dfa0f2-a13e-4132-96c1-069e1cc18dfc
📒 Files selected for processing (2)
nemoclaw/src/index.tsnemoclaw/src/register.test.ts
…t.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Jason Ma <jama@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Jason Ma <jama@nvidia.com>
There was a problem hiding this comment.
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 `@nemoclaw/src/index.ts`:
- Around line 340-350: The footer logic currently prefers onboardCfg for
bannerEndpoint/bannerProvider causing stale values; update initialization so
bannerEndpoint and bannerProvider prefer probed.endpoint and probed.provider
first (like bannerModel does), falling back to
describeOnboardEndpoint(onboardCfg)/describeOnboardProvider(onboardCfg) only if
probed values are falsy, and then to the same string defaults
("build.nvidia.com", "NVIDIA Endpoints"); adjust the assignments around
bannerEndpoint, bannerProvider, probed, and onboardCfg accordingly so the live
probe wins.
🪄 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: 6ab4665e-bbe6-4f9e-ba61-9cc07470c244
📒 Files selected for processing (2)
nemoclaw/src/index.tsnemoclaw/src/register.test.ts
| let bannerEndpoint = onboardCfg ? describeOnboardEndpoint(onboardCfg) : ""; | ||
| let bannerProvider = onboardCfg ? describeOnboardProvider(onboardCfg) : ""; | ||
| let bannerModel = onboardCfg?.model ?? ""; | ||
| let probedModel = ""; | ||
|
|
||
| if (!bannerEndpoint || !bannerProvider || !bannerModel) { | ||
| const probed = probeOpenShellInference(); | ||
| if (!bannerEndpoint) bannerEndpoint = probed.endpoint; | ||
| if (!bannerProvider) bannerProvider = probed.provider; | ||
| if (!bannerModel) bannerModel = probed.model; | ||
| probedModel = probed.model; | ||
| } | ||
| // Prefer the live gateway model over the stale onboard config model. | ||
| let bannerModel = probed.model || onboardCfg?.model || ""; | ||
|
|
||
| if (!bannerEndpoint) bannerEndpoint = probed.endpoint; | ||
| if (!bannerProvider) bannerProvider = probed.provider; | ||
|
|
||
| if (!bannerEndpoint) bannerEndpoint = "build.nvidia.com"; | ||
| if (!bannerProvider) bannerProvider = "NVIDIA Endpoints"; | ||
| if (!bannerModel) bannerModel = "nvidia/nemotron-3-super-120b-a12b"; |
There was a problem hiding this comment.
Keep the footer banner sourced from the live probe, not just the model.
bannerModel now tracks the probed gateway, but bannerEndpoint and bannerProvider still prefer onboardCfg whenever it exists. After a runtime openshell inference set, the footer can still show stale endpoint/provider metadata, so the UI does not fully reflect the live gateway state this PR is aiming for.
♻️ Suggested fix
- let bannerEndpoint = onboardCfg ? describeOnboardEndpoint(onboardCfg) : "";
- let bannerProvider = onboardCfg ? describeOnboardProvider(onboardCfg) : "";
+ let bannerEndpoint = probed.endpoint || (onboardCfg ? describeOnboardEndpoint(onboardCfg) : "");
+ let bannerProvider = probed.provider || (onboardCfg ? describeOnboardProvider(onboardCfg) : "");📝 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.
| let bannerEndpoint = onboardCfg ? describeOnboardEndpoint(onboardCfg) : ""; | |
| let bannerProvider = onboardCfg ? describeOnboardProvider(onboardCfg) : ""; | |
| let bannerModel = onboardCfg?.model ?? ""; | |
| let probedModel = ""; | |
| if (!bannerEndpoint || !bannerProvider || !bannerModel) { | |
| const probed = probeOpenShellInference(); | |
| if (!bannerEndpoint) bannerEndpoint = probed.endpoint; | |
| if (!bannerProvider) bannerProvider = probed.provider; | |
| if (!bannerModel) bannerModel = probed.model; | |
| probedModel = probed.model; | |
| } | |
| // Prefer the live gateway model over the stale onboard config model. | |
| let bannerModel = probed.model || onboardCfg?.model || ""; | |
| if (!bannerEndpoint) bannerEndpoint = probed.endpoint; | |
| if (!bannerProvider) bannerProvider = probed.provider; | |
| if (!bannerEndpoint) bannerEndpoint = "build.nvidia.com"; | |
| if (!bannerProvider) bannerProvider = "NVIDIA Endpoints"; | |
| if (!bannerModel) bannerModel = "nvidia/nemotron-3-super-120b-a12b"; | |
| let bannerEndpoint = probed.endpoint || (onboardCfg ? describeOnboardEndpoint(onboardCfg) : ""); | |
| let bannerProvider = probed.provider || (onboardCfg ? describeOnboardProvider(onboardCfg) : ""); | |
| // Prefer the live gateway model over the stale onboard config model. | |
| let bannerModel = probed.model || onboardCfg?.model || ""; | |
| if (!bannerEndpoint) bannerEndpoint = probed.endpoint; | |
| if (!bannerProvider) bannerProvider = probed.provider; | |
| if (!bannerEndpoint) bannerEndpoint = "build.nvidia.com"; | |
| if (!bannerProvider) bannerProvider = "NVIDIA Endpoints"; | |
| if (!bannerModel) bannerModel = "nvidia/nemotron-3-super-120b-a12b"; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nemoclaw/src/index.ts` around lines 340 - 350, The footer logic currently
prefers onboardCfg for bannerEndpoint/bannerProvider causing stale values;
update initialization so bannerEndpoint and bannerProvider prefer
probed.endpoint and probed.provider first (like bannerModel does), falling back
to describeOnboardEndpoint(onboardCfg)/describeOnboardProvider(onboardCfg) only
if probed values are falsy, and then to the same string defaults
("build.nvidia.com", "NVIDIA Endpoints"); adjust the assignments around
bannerEndpoint, bannerProvider, probed, and onboardCfg accordingly so the live
probe wins.
) ## Summary After a runtime `openshell inference set`, the OpenClaw TUI footer continued showing the onboard-time model because the plugin only read the model from the on-disk onboard config (which is never updated at runtime). This fix makes the plugin always probe the live gateway inference state at registration time and prefer that result for both the banner display and registered provider model. ## Related Issue Fixes NVIDIA#2608 ## Changes - `nemoclaw/src/index.ts`: Always call `probeOpenShellInference()` unconditionally at plugin registration (instead of only when the onboard config is missing fields); prefer `probed.model` over `onboardCfg?.model` for `bannerModel` and the registered provider model catalog - `nemoclaw/src/index.ts`: In `activeModelEntries`, flip precedence so the live `fallbackModel` overrides the stale onboard config model - `nemoclaw/src/register.test.ts`: Add regression test asserting that the live gateway model wins over the stale onboard config model after a runtime switch ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Verification - [x] `npx prek run --all-files` passes - [x] `npm test` passes - [x] Tests added or updated for new or changed behavior - [x] No secrets, API keys, or credentials committed - [ ] Docs updated for user-facing behavior changes - [ ] `make docs` builds without warnings (doc changes only) - [ ] 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) ## AI Disclosure - [x] AI-assisted — tool: Claude Code --- Signed-off-by: Jason Ma <jama@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Model selection now always uses live gateway probe results (and falls back to empty/default when none), ensuring registration, UI banner, and endpoints reflect current runtime gateway info rather than stale onboard config. * **Tests** * Added a regression test verifying runtime probing overrides outdated onboard model data and that registration and logs reflect the probed model. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Jason Ma <jama@nvidia.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: J. Yaunches <jyaunches@nvidia.com> Co-authored-by: Aaron Erickson 🦞 <aerickson@nvidia.com>
Summary
After a runtime
openshell inference set, the OpenClaw TUI footer continued showing the onboard-time model because the plugin only read the model from the on-disk onboard config (which is never updated at runtime). This fix makes the plugin always probe the live gateway inference state at registration time and prefer that result for both the banner display and registered provider model.Related Issue
Fixes #2608
Changes
nemoclaw/src/index.ts: Always callprobeOpenShellInference()unconditionally at plugin registration (instead of only when the onboard config is missing fields); preferprobed.modeloveronboardCfg?.modelforbannerModeland the registered provider model catalognemoclaw/src/index.ts: InactiveModelEntries, flip precedence so the livefallbackModeloverrides the stale onboard config modelnemoclaw/src/register.test.ts: Add regression test asserting that the live gateway model wins over the stale onboard config model after a runtime switchType of Change
Verification
npx prek run --all-filespassesnpm testpassesmake docsbuilds without warnings (doc changes only)AI Disclosure
Signed-off-by: Jason Ma jama@nvidia.com
Summary by CodeRabbit
Bug Fixes
Tests