fix(cli): guide setup into plugin configuration#358
Conversation
WalkthroughSetup now prompts to continue into plugin configuration after saving the base config. It adds scope-specific plugin command helpers, standardizes plugin cancellation text, and extends CLI coverage for the new flow. ChangesContinue-to-plugins flow
Estimated code review effort: 3 (Moderate) | ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/cli/src/setup.rs`:
- Around line 137-139: The `run()` flow in `crates/cli/src/setup.rs` treats
`continue_to_plugins(...)` as fatal when the optional plugin prompt is
interrupted, even though an explicit “no” returns `Ok(())`; make the
cancellation path match the decline path by handling the `plugin_prompt_error`
result in `continue_to_plugins`/`run()` and converting Ctrl+C or EOF at that
prompt into a graceful skip instead of propagating an error, unless the intended
contract is to fail the whole `config` command.
🪄 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: ASSERTIVE
Plan: Enterprise
Run ID: cc945db1-7af9-4dd5-b75b-f7b926806f6c
📒 Files selected for processing (5)
crates/cli/src/plugins.rscrates/cli/src/setup.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rsdocs/nemo-relay-cli/basic-usage.mdx
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (13)
**/*.mdx
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)
MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)
**/*.mdx: In MDX files, top-of-file comments must use JSX comment delimiters:{/*to open and*/}to close; do not use HTML comments for MDX SPDX headers.
New or regenerated MDX files must use{/* ... */}for top-of-file SPDX comments.
Files:
docs/nemo-relay-cli/basic-usage.mdx
**/*
📄 CodeRabbit inference engine (AGENTS.md)
Keep SPDX headers on source, docs, scripts, and configuration files.
Files:
docs/nemo-relay-cli/basic-usage.mdxcrates/cli/src/setup/model.rscrates/cli/src/plugins.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
docs/**/*.{md,mdx}: Keep documentation underdocs/valid for Fern tooling and external links, including Markdown/MDX link checks where applicable.
Update relevant reference docs and embedded examples when public behavior, bindings, examples, or workspace structure change.
Files:
docs/nemo-relay-cli/basic-usage.mdx
**/*.{rs,go,js,ts,py,html,md,mdx,toml,yml,yaml,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license headers in all source files using the correct comment syntax for the file type.
Files:
docs/nemo-relay-cli/basic-usage.mdxcrates/cli/src/setup/model.rscrates/cli/src/plugins.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
**/*.{md,mdx}
📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)
**/*.{md,mdx}: Prefer the documented public API rather than internal shortcuts.
Keep package names, repository references, and build commands current.
Update entry-point docs when examples or reading paths change.
Keep release-process and release-notes guidance in repository-maintainer docs such asRELEASING.md, not in user-facing docs pages orCHANGELOG.md.
Keep stable user-facing wrappers at thescripts/root in docs and examples; only point at namespaced helper paths when documenting internal maintenance work.
When detailed dynamic plugin guides exist, keep Rust native plugin examples, Python worker plugin examples, andgrpc-v1protocol details on separate pages.
Dynamic plugin manifests in docs and examples should usecompat.relay = ">=0.5,<1.0"unless deliberately narrower.
Update relevant getting-started or reference docs when the associated behavior or examples change.
Ensure example commands still match current package names and paths.
Dynamic plugin entry pages should link to native, worker, Rust example, Python example, and protocol pages when those pages exist.
When the docs site changes, runjust docs;./scripts/build-docs.sh htmlremains the compatibility wrapper.
**/*.{md,mdx}: Document native and worker plugins as trusted extensions: native plugins are in-process and unsandboxed, while worker plugins provide process isolation but not a security sandbox.
When detailed dynamic plugin guides exist, keep Rust native, Python worker, andgrpc-v1protocol details on separate pages.
Files:
docs/nemo-relay-cli/basic-usage.mdx
docs/**/*.mdx
📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)
Update documentation if activation or usage changes
Files:
docs/nemo-relay-cli/basic-usage.mdx
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings,
documentation, integrations, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile skills/ # Published Codex/agent skills for NeMo Relay usage patternsPrerequisites
Insta...
Files:
docs/nemo-relay-cli/basic-usage.mdxcrates/cli/src/setup/model.rscrates/cli/src/plugins.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}
⚙️ CodeRabbit configuration file
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.
Files:
docs/nemo-relay-cli/basic-usage.mdx
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Usecargo fmt(rustfmt defaults) for Rust code changed in the core runtime or Rust-facing API surface.
Runcargo clippy -- -D warningsand keep Rust code warning-free; all warnings are treated as errors.
Use Rustsnake_casenaming conventions.Use
snake_casefor Rust identifiers.
Files:
crates/cli/src/setup/model.rscrates/cli/src/plugins.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
**/*.{rs,py,go,ts,js,mjs,cjs,jsx,tsx,c,h}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions: Rust and Python use
snake_case, C FFI exports use thenemo_relay_prefix, Go public APIs usePascalCase, and Node.js usescamelCase.
Files:
crates/cli/src/setup/model.rscrates/cli/src/plugins.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
crates/**/*.{rs,py,ts,js,c,h}
📄 CodeRabbit inference engine (AGENTS.md)
crates/**/*.{rs,py,ts,js,c,h}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at wrapper layers.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/cli/src/setup/model.rscrates/cli/src/plugins.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
crates/**/src/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
crates/**/src/**/*.rs: Keep the stable plugin boundary explicit: native plugins cross a C ABI, and worker plugins crossgrpc-v1. Do not pass Rust runtime types, trait objects, futures, or allocator-owned strings across the native dynamic-library boundary.
Manifest validation must cover kind, compatibility, load contract, integrity, capability mismatch, and disabled-plugin behavior.
The native loader must keep libraries alive until registered callbacks are cleared and must deregister plugin kinds before unload.
Runtime helpers must cover marks, scopes, continuations, and isolated scope stacks.
plugins list,plugins inspect, andplugins validatemust report lifecycle and compatibility status without leaking secret config.
The top-leveldoctorcommand must report resolved dynamic plugin and host configuration status.
Files:
crates/cli/src/setup/model.rscrates/cli/src/plugins.rscrates/cli/src/setup.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/cli/tests/coverage/setup_tests.rs
🔇 Additional comments (5)
crates/cli/tests/coverage/setup_tests.rs (1)
577-654: LGTM!docs/nemo-relay-cli/basic-usage.mdx (1)
172-177: LGTM!crates/cli/src/plugins.rs (1)
327-327: LGTM!Also applies to: 613-613, 1372-1372
crates/cli/src/setup/model.rs (1)
11-11: LGTM!Also applies to: 36-64
crates/cli/src/setup.rs (1)
30-31: LGTM!
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
a767764 to
8db2208
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
crates/cli/src/setup.rs (1)
137-139: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winInterrupt/EOF at either plugin-related prompt still fails the whole
configcommand.This is the same asymmetry flagged in a previous review: an explicit "no" at
continue_to_plugins's confirm returnsOk(())viaprint_plugins_skipped, but Ctrl+C/EOF at that same prompt goes throughplugin_prompt_errorand propagates asErr, failing the entirenemo-relay configinvocation with a nonzero exit — even though the primary goal (savingconfig.toml) already succeeded.The same pattern now also applies one level deeper: if the user accepts the prompt and then cancels the nested plugin editor (via
plugins.rs'scancelled_error/menu_error/editor_error, all wrapped bycrate::plugins::edit(...).map_err(...)here), that cancellation is likewise surfaced as a hardErrfromrun(), not a graceful skip — despiteconfig.tomlstill being saved correctly in both cases.Since
plugin_prompt_error_reports_cancellation_with_base_saved_and_resumelocks in the current "Err on interrupt" behavior, this looks intentional, but it's worth confirming that failing the overallconfigcommand on an interrupted optional continuation step is the desired contract for scripts/automation that treat any nonzero exit as failure.Also applies to: 148-191
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/cli/src/setup.rs` around lines 137 - 139, The optional plugin continuation path in `continue_to_plugins` and the nested `crate::plugins::edit(...).map_err(...)` flow currently turn Ctrl+C/EOF into hard errors that fail `run()` even after `config.toml` was already saved. Update these prompt handlers so interruption at the plugin-related prompts is treated like an intentional skip (same as the explicit “no” path) and returns `Ok(())` instead of propagating `plugin_prompt_error`, keeping `nemo-relay config` successful when only the optional plugin step is canceled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/cli/src/plugins.rs`:
- Around line 326-328: The cancellation text is duplicated across
cancelled_error, menu_error, and editor_error, so extract the shared wording
into a single constant or helper and have all three functions reference it.
Update the CliError::Config construction sites in plugins.rs to use that shared
symbol instead of repeating the literal, keeping the message consistent
everywhere.
---
Duplicate comments:
In `@crates/cli/src/setup.rs`:
- Around line 137-139: The optional plugin continuation path in
`continue_to_plugins` and the nested `crate::plugins::edit(...).map_err(...)`
flow currently turn Ctrl+C/EOF into hard errors that fail `run()` even after
`config.toml` was already saved. Update these prompt handlers so interruption at
the plugin-related prompts is treated like an intentional skip (same as the
explicit “no” path) and returns `Ok(())` instead of propagating
`plugin_prompt_error`, keeping `nemo-relay config` successful when only the
optional plugin step is canceled.
🪄 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: ASSERTIVE
Plan: Enterprise
Run ID: 400fa6ba-46b5-43f6-9fd5-df25e749f556
📒 Files selected for processing (4)
crates/cli/src/plugins.rscrates/cli/src/setup.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Check / Run
🧰 Additional context used
📓 Path-based instructions (8)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Usecargo fmt(rustfmt defaults) for Rust code changed in the core runtime or Rust-facing API surface.
Runcargo clippy -- -D warningsand keep Rust code warning-free; all warnings are treated as errors.
Use Rustsnake_casenaming conventions.Use
snake_casefor Rust identifiers.
Files:
crates/cli/src/plugins.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
**/*
📄 CodeRabbit inference engine (AGENTS.md)
Keep SPDX headers on source, docs, scripts, and configuration files.
Files:
crates/cli/src/plugins.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
**/*.{rs,py,go,ts,js,mjs,cjs,jsx,tsx,c,h}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions: Rust and Python use
snake_case, C FFI exports use thenemo_relay_prefix, Go public APIs usePascalCase, and Node.js usescamelCase.
Files:
crates/cli/src/plugins.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
crates/**/*.{rs,py,ts,js,c,h}
📄 CodeRabbit inference engine (AGENTS.md)
crates/**/*.{rs,py,ts,js,c,h}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at wrapper layers.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/cli/src/plugins.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
**/*.{rs,go,js,ts,py,html,md,mdx,toml,yml,yaml,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license headers in all source files using the correct comment syntax for the file type.
Files:
crates/cli/src/plugins.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
crates/**/src/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
crates/**/src/**/*.rs: Keep the stable plugin boundary explicit: native plugins cross a C ABI, and worker plugins crossgrpc-v1. Do not pass Rust runtime types, trait objects, futures, or allocator-owned strings across the native dynamic-library boundary.
Manifest validation must cover kind, compatibility, load contract, integrity, capability mismatch, and disabled-plugin behavior.
The native loader must keep libraries alive until registered callbacks are cleared and must deregister plugin kinds before unload.
Runtime helpers must cover marks, scopes, continuations, and isolated scope stacks.
plugins list,plugins inspect, andplugins validatemust report lifecycle and compatibility status without leaking secret config.
The top-leveldoctorcommand must report resolved dynamic plugin and host configuration status.
Files:
crates/cli/src/plugins.rscrates/cli/src/setup/model.rscrates/cli/src/setup.rs
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings,
documentation, integrations, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile skills/ # Published Codex/agent skills for NeMo Relay usage patternsPrerequisites
Insta...
Files:
crates/cli/src/plugins.rscrates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/cli/tests/coverage/setup_tests.rs
🔇 Additional comments (4)
crates/cli/src/setup/model.rs (1)
11-11: LGTM!Also applies to: 36-64
crates/cli/src/setup.rs (2)
30-31: LGTM!
193-201: LGTM!crates/cli/tests/coverage/setup_tests.rs (1)
577-654: LGTM! Good coverage of scope mapping and both cancellation/failure message-formatting paths.
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/cli/src/setup.rs`:
- Around line 160-166: The plugin setup error message is being constructed in
multiple places, which risks drift between the prompt and edit error paths.
Extract the shared “plugin setup did not complete; base configuration remains
saved. Resume with ...” formatting into a small helper in setup.rs, and reuse it
from the error handling around the prompt/edit flow via
plugins_resume_command(scope) so both branches emit the same message with the
same Cause text.
🪄 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: ASSERTIVE
Plan: Enterprise
Run ID: e91e6b72-5db3-4a5b-b039-aede4a6c08f5
📒 Files selected for processing (4)
crates/cli/src/plugins.rscrates/cli/src/setup.rscrates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workFollow Rust naming conventions, including
snake_caseidentifiers and Rust-facing runtime API shapes.
**/*.rs: When changing the core runtime or Rust-facing API surface, format Rust code withcargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and passcargo deny check.
When touching the core Rust crate, run the Rust tests and the other affected binding test suites because the bindings depend on the core runtime.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
**/*.{rs,py,js,ts,mjs,c,h,md,toml,yml,yaml,sh,json,go}
📄 CodeRabbit inference engine (AGENTS.md)
Keep SPDX headers on source files, documentation, scripts, and configuration files.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
**/*.{rs,py,go,js,ts,jsx,tsx,md,mdx,toml,yaml,yml,html}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
All source files must include an SPDX license header using the comment syntax appropriate for the file type, with SPDX-FileCopyrightText for 2026 NVIDIA CORPORATION & AFFILIATES and SPDX-License-Identifier: Apache-2.0.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use the naming conventions appropriate to each language: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
**/*.{rs,py,go,js,ts,md,mdx,toml,yaml,yml,json}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Avoid using
SONAR_IGNORE_START/SONAR_IGNORE_ENDexcept for documented false positives; keep the ignored block small, add a brief explanatory comment, and call it out in the PR description.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
**/*.{rs,py,go,js,ts,wasm}
📄 CodeRabbit inference engine (.agents/skills/maintain-observability/SKILL.md)
Ensure binding-native wrappers expose the same observability configuration knobs and lifecycle behavior across Rust, Python, Go, Node.js, and WebAssembly.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
**/*.{rs,rlib}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.{rs,rlib}: If any Rust code changed, always runjust test-rust.
If any Rust code changed, also runcargo fmt --all.
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings,
documentation, integrations, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile skills/ # Published Codex/agent skills for NeMo Relay usage patternsPrerequisites
Insta...
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rscrates/cli/src/setup.rscrates/cli/src/plugins.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/cli/tests/coverage/plugins_tests.rscrates/cli/tests/coverage/setup_tests.rs
🔇 Additional comments (5)
crates/cli/src/plugins.rs (1)
33-34: LGTM!Also applies to: 329-329, 610-619, 1366-1378
crates/cli/src/setup.rs (2)
149-183: Ctrl+C-at-prompt fix looks correct.Interruption now mirrors the explicit "no" path (skip +
Ok(())), resolving the earlier asymmetry between decline and interrupt.
185-194: LGTM!crates/cli/tests/coverage/setup_tests.rs (1)
579-627: LGTM!crates/cli/tests/coverage/plugins_tests.rs (1)
618-637: LGTM!
…etup Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/cli/src/setup/model.rs (1)
190-213: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winPreserve legacy
[plugins]until migration runs
read_existing_defaults()still accepts oldconfig.tomlfiles, butwrite_or_merge()always drops the existingpluginstable before rewriting. If an unmigrated config reachesnemo-relay config, that plugin data is lost with no warning or backup. Add an explicit migration/guard here, or keep the legacy block until it has been moved toplugins.toml.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/cli/src/setup/model.rs` around lines 190 - 213, The write_or_merge function is dropping the legacy plugins table unconditionally, which can erase unmigrated config data. Update write_or_merge in model.rs to either preserve the existing [plugins] block unless a migration step has already moved it to plugins.toml, or add an explicit migration/guard before calling existing.remove("plugins"). Keep the behavior tied to the merge flow around read_existing_defaults and merge_agents_entry so legacy plugin settings are not lost during nemo-relay config writes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/cli/src/setup/model.rs`:
- Around line 190-213: The write_or_merge function is dropping the legacy
plugins table unconditionally, which can erase unmigrated config data. Update
write_or_merge in model.rs to either preserve the existing [plugins] block
unless a migration step has already moved it to plugins.toml, or add an explicit
migration/guard before calling existing.remove("plugins"). Keep the behavior
tied to the merge flow around read_existing_defaults and merge_agents_entry so
legacy plugin settings are not lost during nemo-relay config writes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 0960727f-e337-4cee-9f83-f7a8b3eb7fef
📒 Files selected for processing (2)
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workFollow Rust naming conventions, including
snake_caseidentifiers and Rust-facing runtime API shapes.
**/*.rs: When changing the core runtime or Rust-facing API surface, format Rust code withcargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and passcargo deny check.
When touching the core Rust crate, run the Rust tests and the other affected binding test suites because the bindings depend on the core runtime.
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
**/*.{rs,py,js,ts,mjs,c,h,md,toml,yml,yaml,sh,json,go}
📄 CodeRabbit inference engine (AGENTS.md)
Keep SPDX headers on source files, documentation, scripts, and configuration files.
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
**/*.{rs,py,go,js,ts,jsx,tsx,md,mdx,toml,yaml,yml,html}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
All source files must include an SPDX license header using the comment syntax appropriate for the file type, with SPDX-FileCopyrightText for 2026 NVIDIA CORPORATION & AFFILIATES and SPDX-License-Identifier: Apache-2.0.
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use the naming conventions appropriate to each language: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
**/*.{rs,py,go,js,ts,md,mdx,toml,yaml,yml,json}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Avoid using
SONAR_IGNORE_START/SONAR_IGNORE_ENDexcept for documented false positives; keep the ignored block small, add a brief explanatory comment, and call it out in the PR description.
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
**/*.{rs,py,go,js,ts,wasm}
📄 CodeRabbit inference engine (.agents/skills/maintain-observability/SKILL.md)
Ensure binding-native wrappers expose the same observability configuration knobs and lifecycle behavior across Rust, Python, Go, Node.js, and WebAssembly.
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
**/*.{rs,rlib}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.{rs,rlib}: If any Rust code changed, always runjust test-rust.
If any Rust code changed, also runcargo fmt --all.
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings.
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings,
documentation, integrations, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile skills/ # Published Codex/agent skills for NeMo Relay usage patternsPrerequisites
Insta...
Files:
crates/cli/src/setup/model.rscrates/cli/tests/coverage/setup_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/cli/tests/coverage/setup_tests.rs
🔇 Additional comments (2)
crates/cli/src/setup/model.rs (1)
36-64: LGTM!crates/cli/tests/coverage/setup_tests.rs (1)
449-475: LGTM!Also applies to: 578-628
|
/merge |
1 similar comment
|
/merge |
Overview
The interactive
nemo-relay configwizard currently ends after writing the baseconfig.toml, leaving a first-time user to discover and runnemo-relay plugins editas a separate step.This change connects those existing flows. After the base configuration is saved, Relay asks whether the user wants to configure plugins now. Accepting the prompt opens the existing plugin editor in-process; declining keeps the completed base configuration and prints the exact command for resuming later.
Details
Guided setup flow
The interactive path now proceeds as follows:
nemo-relay config.config.tomland confirmLooks good?.Configure Relay plugins now? [Y/n].The new prompt controls only whether the plugin editor opens. It does not control the already-completed base configuration save, and selecting Yes does not save plugin changes automatically.
Plugin editor walkthrough
When the user selects Yes, the existing
plugins editmenu opens:p) — shows the resultingplugins.tomlbefore writing it.s) — writesplugins.tomland completes the guided flow.q) — exits without saving plugin changes; the baseconfig.tomlremains saved.The existing navigation remains unchanged: arrow keys or
j/kmove through the menu, Enter/Space selects, and the existing reset/clear/help shortcuts continue to work.Scope mapping and resume behavior
plugins.tomlnemo-relay plugins edit --projectplugins.tomlnemo-relay plugins editplugins.tomlbecause project configuration takes precedencenemo-relay plugins edit --projectCancellation and partial setup
The base configuration is never rolled back after it has been saved:
Compatibility and implementation
plugins::editimplementation rather than adding a second editor or duplicating plugin logic.nemo-relay plugins editusage and menu behavior unchanged, aside from clearer cancellation wording.nemo-relay config --resetunchanged.Validation completed:
cargo fmt --all --checkcargo clippy -p nemo-relay-cli --all-targets -- -D warningscargo test -p nemo-relay-cli— 704 tests passedNo breaking changes.
Where should the reviewer start?
Start with
continue_to_pluginsincrates/cli/src/setup.rs. It contains the new post-save handoff and partial-setup error handling. Then review:crates/cli/src/setup/model.rsfor setup-scope to plugin-scope mapping.crates/cli/tests/coverage/setup_tests.rsfor mapping and error-message coverage.crates/cli/src/plugins.rsfor the cancellation wording clarification.Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit
New Features
config.toml, with an option to continue now or resume later using a clear follow-up command.Bug Fixes
Tests