Skip to content

feat: layer code-driven plugin config#199

Open
zhongxuanwang-nv wants to merge 11 commits into
NVIDIA:mainfrom
zhongxuanwang-nv:feat/relay-183-layer-code-driven-plugin-config
Open

feat: layer code-driven plugin config#199
zhongxuanwang-nv wants to merge 11 commits into
NVIDIA:mainfrom
zhongxuanwang-nv:feat/relay-183-layer-code-driven-plugin-config

Conversation

@zhongxuanwang-nv
Copy link
Copy Markdown
Member

@zhongxuanwang-nv zhongxuanwang-nv commented Jun 1, 2026

Overview

Layers code-driven plugin configuration through each binding's plugin.initialize(...) path over materialized file-backed plugins.toml configuration, while preserving deterministic file discovery and clear source reporting.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

  • Added shared core resolution for discovered plugin config files plus an optional code-driven plugin.initialize(...) overlay.
  • Preserved file-backed discovery from system, project, and user plugins.toml locations, with code config layered at higher precedence when supplied to binding initialization.
  • Removed the public .layer(...) helper surfaces and the ad-hoc --plugin-config / x-nemo-relay-plugin-config paths so callers use config files plus binding initialization instead.
  • Kept direct materialized-config initialization APIs available for callers that already have a complete PluginConfig.
  • Added clearer effective-source/error reporting for plugin config activation and doctor/dry-run output.
  • Clarified that layered configs reject duplicate component kind values in either layer because matching repeated plugin instances by kind alone is ambiguous; fully materialized configs can still contain repeated kinds when the plugin supports multiple components.
  • Added tests across core, CLI, FFI, Python, Node.js, Go, and WebAssembly surfaces, including Node coverage for plugin.initialize() with no arguments loading project plugins.toml.
  • Updated plugin configuration docs and agent skill guidance to describe discovery, precedence, file-source conflicts, quick testing, and code-driven overlays.

Quick functional check:

# .nemo-relay/plugins.toml
version = 1

[[components]]
kind = "observability"
enabled = false

[components.config.atof]
enabled = true
filename = "events.jsonl"
from nemo_relay import plugin

await plugin.initialize({
    "components": [{
        "kind": "observability",
        "config": {
            "atof": {
                "mode": "overwrite",
            },
        },
    }],
})

Effective behavior: NeMo Relay discovers .nemo-relay/plugins.toml, keeps enabled = false, atof.enabled = true, and filename = "events.jsonl" from the file, then applies mode = "overwrite" from the code-driven overlay. If either layer contains duplicate kind entries, initialization fails instead of guessing which instance to update.

Validation:

  • cargo fmt --all
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test -p nemo-relay
  • cargo test -p nemo-relay-adaptive
  • cargo test -p nemo-relay-ffi
  • CLI integration and targeted CLI plugin/session tests
  • just test-python
  • just test-node
  • just test-go
  • cargo test -p nemo-relay-wasm
  • just docs
  • SKIP=attributions-rust uv run pre-commit run --all-files

Local environment notes: just test-wasm is blocked on this machine because the Homebrew Rust sysroot is missing the wasm32-unknown-unknown target, and the Rust attribution pre-commit hook is skipped locally because cargo-about is not installed.

Where should the reviewer start?

Start with crates/core/src/plugin.rs for discovered config resolution, overlay semantics, and duplicate-kind rejection. Then review crates/node/tests/plugin_tests.mjs for the no-argument plugin.initialize() coverage and docs/build-plugins/plugin-configuration-files.mdx for the public behavior description.

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

Summary by CodeRabbit

  • New Features

    • Automatic discovery and layered merging of file-backed plugin config; initialize() across bindings accepts an optional overlay.
    • Dry-run and live status now show the resolved plugin configuration and which file/source provided it.
    • Diagnostics/doctor output includes the effective plugin-config source.
  • Breaking Changes

    • Removed the CLI --plugin-config flag and the corresponding relay header.
  • Documentation

    • Expanded plugin config docs with discovery, precedence, layering, and examples.

Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

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

This PR implements a plugin configuration discovery and layering system: discover and merge file-backed plugin config (plugins.toml or inline [plugins].config), allow an optional code overlay at initialization, track the winning file-backed source in GatewayConfig.plugin_config_source, remove per-request/CLI plugin-config overrides and header forwarding, and expose discovered-config initialization across FFI and language bindings with updated tests and docs.

Changes

Plugin Configuration Layering and CLI Integration

Layer / File(s) Summary
Core TOML discovery and JSON layering
crates/core/src/plugin.rs, crates/core/Cargo.toml, crates/core/tests/unit/plugin_tests.rs
Adds recursive JSON/TOML merge behavior with component kind-based merging, per-file duplicate-kind validation, discovery of candidate plugins.toml paths, resolve_plugin_config_layers() / ResolvedPluginConfig, and initialize_plugins_from_discovered_config() with unit tests and toml = "0.9" dependency.
CLI GatewayConfig source tracking and session handling
crates/cli/src/config.rs
Adds GatewayConfig.plugin_config_source: Option<String>, removes --plugin-config/env/CLI fields from ServerArgs/RunCommand/HookForwardCommand, makes session config use gateway-level plugin_config (no header override), sets plugin_config_source when inline [plugins].config is found in config.toml, and treats plugins.toml vs inline config conflicts as errors.
CLI server plugin activation with source attribution
crates/cli/src/server.rs
serve_listener() passes optional plugin_config and plugin_config_source into plugin initialization; initializer accepts source: Option<&str> (defaulting to "plugin config") and includes source label in config/activation error messages.
CLI diagnostics and live status output
crates/cli/src/doctor.rs, crates/cli/src/launcher.rs
nemo-relay doctor plugin check details now include the resolved plugin_config_source; launcher live-status and verbose inspection conditionally show plugin_config_source.
Hook-forward: remove per-session plugin config
crates/cli/src/installer.rs
Removes CLI validation and forwarding of --plugin-config and the x-nemo-relay-plugin-config header; gateway_headers() now takes only profile, session metadata, and gateway mode.
FFI C API for discovered-config initialization
crates/ffi/nemo_relay.h, crates/ffi/src/api/plugin.rs, crates/ffi/src/api/mod.rs
Adds nemo_relay_initialize_plugins_from_discovered_config(config_json, out_json) C API, updates safety docs to document allocated out_json, and maps errors/status; imports layer_plugin_config where needed.
Node.js binding: optional config overlay
crates/node/plugin.d.ts, crates/node/plugin.js, crates/node/src/api/mod.rs, crates/node/tests/plugin_tests.mjs
plugin.initialize(config?) accepts an optional overlay, delegates to native initialize_plugins_from_discovered_config via NAPI, and includes integration tests exercising project plugins.toml discovery and overlay behavior.
Python binding: optional config overlay
python/nemo_relay/_native.pyi, crates/python/src/py_plugin.rs, python/nemo_relay/plugin.py, python/nemo_relay/plugin.pyi, python/tests/test_plugin_config.py
Adds native stub and Python wrapper initialize_plugins_from_discovered_config, makes plugin.initialize(config=None) accept omitted overlays and call into discovered-config initializer; adds integration test validating layering.
WebAssembly binding: optional config overlay
crates/wasm/src/api/mod.rs, crates/wasm/wrappers/esm/plugin.d.ts, crates/wasm/wrappers/esm/plugin.js, crates/wasm/wrappers/nodejs/plugin.js
WASM initialize_plugins treats null/undefined as None, converts JS values to JSON, calls discovered-config initializer, and updates wrapper typings/signatures to accept optional config.
Go binding: discovered-config initialization & tests
go/nemo_relay/plugin.go, go/nemo_relay/plugin_gap_test.go
Go wrapper switches to new discovered-config FFI entrypoint, fixes JSON marshaling helpers, and adds an integration test validating code-overlay layering over project plugins.toml.
CLI integration and coverage tests
crates/cli/tests/cli_tests.rs, crates/cli/tests/coverage/*, crates/ffi/tests/unit/api/plugin_tests.rs
Adds dry-run and flag-rejection CLI tests, updates many coverage tests to include plugin_config_source: None or to remove deprecated CLI plugin-config fields, strengthens server error assertions, and updates doctor tests to assert source reporting.
Documentation: discovery, precedence, and layering
docs/build-plugins/plugin-configuration-files.mdx, docs/build-plugins/register-behavior.mdx
Extensive docs added/updated to explain discovery locations, precedence rules (plugins.toml vs inline config), exclusion of simultaneous file-backed sources, component-kind merge semantics, code-driven overlay usage via binding initialize(...), and verification via --dry-run or binding calls.
Documentation: ATOF and CLI usage
docs/observability-plugin/atof.mdx, docs/nemo-relay-cli/basic-usage.mdx, skills/*
ATOF docs clarify output directory/file creation semantics; CLI docs remove --plugin-config; skill docs recommend using binding layering helper rather than manual nested merging.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title follows Conventional Commits format with type 'feat', no scope, and concise imperative summary under 72 characters.
Description check ✅ Passed Description provides comprehensive overview, detailed changes, reviewer guidance, and related issue reference matching template structure.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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.

@github-actions github-actions Bot added size:L PR is large Feature a new feature lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code labels Jun 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

@zhongxuanwang-nv zhongxuanwang-nv self-assigned this Jun 2, 2026
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@github-actions github-actions Bot added size:XL PR is extra large and removed size:L PR is large labels Jun 2, 2026
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@zhongxuanwang-nv zhongxuanwang-nv marked this pull request as ready for review June 2, 2026 04:17
@zhongxuanwang-nv zhongxuanwang-nv requested a review from a team as a code owner June 2, 2026 04:17
Copy link
Copy Markdown

@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: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/cli/src/config.rs (1)

199-201: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve env-vs-flag provenance for plugin config layers.

ServerArgs.plugin_config is populated by clap from either --plugin-config or NEMO_RELAY_PLUGIN_CONFIG, but apply_cli_plugin_config hardcodes the provenance string as --plugin-config, so env-backed plugin config gets mis-tagged in plugin_config_source. That value is used by doctor, launcher output, and plugin activation error messages—so provenance tracking is incorrect. Thread the actual value source through to apply_code_plugin_config_layer (e.g., label env as NEMO_RELAY_PLUGIN_CONFIG), rather than always using --plugin-config.

Also applies to: 528-530, 806-811

🤖 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/config.rs` around lines 199 - 201, ServerArgs.plugin_config is
being labeled always as "--plugin-config" even when sourced from the
environment; update apply_cli_plugin_config to determine the actual provenance
(flag vs env) and pass that provenance string into
apply_code_plugin_config_layer so plugin_config_source reflects
"NEMO_RELAY_PLUGIN_CONFIG" for env-sourced values and "--plugin-config" for
flag-sourced values; specifically, locate uses of ServerArgs.plugin_config in
apply_cli_plugin_config and change the hardcoded provenance argument to compute
and thread the real source through to apply_code_plugin_config_layer (repeat the
same fix for the other spots noted around the apply_cli_plugin_config usages at
the other ranges so doctor, launcher output, and plugin activation errors get
the correct provenance).
crates/cli/tests/coverage/session_tests.rs (1)

99-107: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Consolidate duplicated GatewayConfig literals through session_test_config().

These inline configs now need the same field churn as the shared helper at Lines 4085-4095. Switching the tests that only need the default test config to session_test_config() would reduce future breakage when GatewayConfig changes again.

Also applies to: 1235-1243, 1305-1313, 1384-1392, 1815-1823, 1891-1899, 1963-1971, 2019-2027, 2065-2073, 2122-2130, 2219-2227, 2334-2342, 2427-2435, 4100-4108

🤖 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/tests/coverage/session_tests.rs` around lines 99 - 107, Replace
the duplicated inline GatewayConfig constructions in session_tests.rs with the
shared helper session_test_config() so tests that only require the default test
setup use that central source of truth; find the inline GatewayConfig instances
(constructed with fields like bind, openai_base_url, anthropic_base_url,
metadata, plugin_config, plugin_config_source) and swap them to let config =
session_test_config(), or if a test needs minor overrides, call
session_test_config() and then modify only those fields; ensure
session_test_config() is imported/visible in session_tests.rs and remove the
duplicated literal to avoid future churn when GatewayConfig changes.
🤖 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/core/src/plugin.rs`:
- Around line 187-197: The layering loop in layer_plugin_config wrongly
collapses multiple overlay components with the same kind into the first base
match (see overlay_components, base_components, json_component_kind,
merge_json_value), breaking configs where validate_plugin_config and
allows_multiple_components permit duplicates; update layer_plugin_config to
either (A) detect duplicate kinds in the overlay for kinds that
allow_multiple_components() and reject early with a clear error, or (B)
implement stable per-instance matching instead of first-match merging — e.g.,
require or derive a per-instance identifier (or positional/occurrence index) and
use that to find the correct base entry before calling merge_json_value, falling
back to appending a new component when no matching instance-id is found. Ensure
behavior is consistent with validate_plugin_config and document which strategy
is used.

In `@crates/ffi/nemo_relay.h`:
- Around line 1116-1125: The header for nemo_relay_layer_plugin_config is
missing ownership semantics for out_json; update the function doc comment to
state that on success the function allocates a NUL-terminated JSON string and
stores it in *out_json and that the caller takes ownership and must free
*out_json using nemo_relay_string_free (or equivalent API) to avoid leaks;
reference nemo_relay_layer_plugin_config and nemo_relay_string_free in the
updated comment so C consumers know who is responsible for deallocation.

In `@crates/ffi/tests/unit/api/plugin_tests.rs`:
- Around line 8-23: Add two negative tests for nemo_relay_layer_plugin_config:
one that passes an invalid JSON C string (e.g., cstring("not-json")) as either
base or overlay and asserts the call returns the FFI error status for bad JSON
(compare to the appropriate NemoRelayStatus variant), and one that passes a null
mutable out_json pointer (use &mut ptr::null_mut() or equivalent) and asserts
the call returns the FFI error status for a null/invalid output pointer; place
these alongside test_ffi_layer_plugin_config_round_trips_merge and use the same
helpers (cstring, returned_json) but do not attempt to dereference or consume
out_json on error paths.

In `@docs/observability-plugin/atof.mdx`:
- Around line 44-45: The docs for ATOF's `output_directory` and `filename` are
inconsistent with runtime behavior: update the description for
`output_directory` to state that the runtime (and the `doctor` command) will
create the directory if missing and that `doctor` only emits a warning rather
than requiring pre-creation; keep `filename` notes about the exporter creating
the file but not parent directories but clarify that parent directories are
created by runtime when using `output_directory`. Edit the `output_directory`
and `filename` table entries in the ATOF docs to reflect this corrected contract
and mention `doctor` by name so readers know where the warning originates.

In `@go/nemo_relay/plugin_gap_test.go`:
- Around line 38-53: Add a failing-path test for LayerPluginConfig that ensures
marshaling errors are returned before crossing the cgo boundary: update
TestLayerPluginConfigRoundTripsMerge (or add a new test) to call
LayerPluginConfig with an unsupported value (e.g., a channel, function, or
cyclic structure) and assert that it returns a non-nil error and does not return
merged JSON; this will exercise the jsonCString/serialization failure path and
ensure the binding surfaces the Go marshaling failure properly.

In `@python/nemo_relay/plugin.py`:
- Around line 291-309: The current layer() call normalizes both base and overlay
via _normalize_object(), but _normalize() removes dict entries with value None
so an overlay intending to set a key to JSON null (e.g. {"config": {"timeout":
None}}) is lost; update the normalization logic so explicit None values from
overlays are preserved: either modify _normalize()/_normalize_object() to not
drop keys whose value is None (or add a flag like preserve_nulls and call
_normalize_object(overlay, preserve_nulls=True) from layer), then call
_layer_plugin_config with the normalized base and the overlay normalized in a
way that retains explicit None overrides (reference functions: layer,
_normalize_object, _normalize).

In `@python/tests/test_plugin_config.py`:
- Around line 7-10: Update the test_layer_plugin_config_round_trips_merge test
to also exercise the typed wrapper path: call plugin.layer with a PluginConfig
instance (e.g., PluginConfig({"a": 1}) and PluginConfig({"b": 2}) or one
PluginConfig and one dict) in addition to the raw dict case and assert the
returned merged JSON equals {"a": 1, "b": 2}; use the PluginConfig symbol from
the module so Python-side conversion is exercised and consider parametrizing the
test if you prefer both forms tested succinctly.

---

Outside diff comments:
In `@crates/cli/src/config.rs`:
- Around line 199-201: ServerArgs.plugin_config is being labeled always as
"--plugin-config" even when sourced from the environment; update
apply_cli_plugin_config to determine the actual provenance (flag vs env) and
pass that provenance string into apply_code_plugin_config_layer so
plugin_config_source reflects "NEMO_RELAY_PLUGIN_CONFIG" for env-sourced values
and "--plugin-config" for flag-sourced values; specifically, locate uses of
ServerArgs.plugin_config in apply_cli_plugin_config and change the hardcoded
provenance argument to compute and thread the real source through to
apply_code_plugin_config_layer (repeat the same fix for the other spots noted
around the apply_cli_plugin_config usages at the other ranges so doctor,
launcher output, and plugin activation errors get the correct provenance).

In `@crates/cli/tests/coverage/session_tests.rs`:
- Around line 99-107: Replace the duplicated inline GatewayConfig constructions
in session_tests.rs with the shared helper session_test_config() so tests that
only require the default test setup use that central source of truth; find the
inline GatewayConfig instances (constructed with fields like bind,
openai_base_url, anthropic_base_url, metadata, plugin_config,
plugin_config_source) and swap them to let config = session_test_config(), or if
a test needs minor overrides, call session_test_config() and then modify only
those fields; ensure session_test_config() is imported/visible in
session_tests.rs and remove the duplicated literal to avoid future churn when
GatewayConfig changes.
🪄 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: a835da00-09af-46cc-826f-6d45f8cb9660

📥 Commits

Reviewing files that changed from the base of the PR and between b0557a9 and 64508db.

📒 Files selected for processing (38)
  • crates/cli/src/config.rs
  • crates/cli/src/doctor.rs
  • crates/cli/src/launcher.rs
  • crates/cli/src/server.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/mod.rs
  • crates/ffi/src/api/plugin.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/node/plugin.d.ts
  • crates/node/plugin.js
  • crates/node/src/api/mod.rs
  • crates/node/tests/plugin_tests.mjs
  • crates/python/src/py_plugin.rs
  • crates/wasm/src/api/mod.rs
  • crates/wasm/tests-js/plugin_tests.mjs
  • crates/wasm/wrappers/esm/index.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/esm/plugin.js
  • crates/wasm/wrappers/nodejs/plugin.js
  • docs/build-plugins/plugin-configuration-files.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/observability-plugin/atof.mdx
  • go/nemo_relay/plugin.go
  • go/nemo_relay/plugin_gap_test.go
  • python/nemo_relay/_native.pyi
  • python/nemo_relay/plugin.py
  • python/nemo_relay/plugin.pyi
  • python/tests/test_plugin_config.py
  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (69)
**/*.{md,rst,html,txt}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)

**/*.{md,rst,html,txt}: Always spell NVIDIA in all caps. Do not use Nvidia, nvidia, nVidia, nVIDIA, or NV.
Use an NVIDIA before a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol after NVIDIA when referring to the company.
Use trademark symbols with product names only when the document type or legal guidance requires them.
Verify official capitalization, spacing, and hyphenation for product names.
Precede NVIDIA product names with NVIDIA on first mention when it is natural and accurate.
Do not rewrite product names for grammar or title-case rules.
Preserve third-party product names according to the owner's spelling.
Include the company name and full model qualifier on first use when it helps identify the model.
Preserve the official capitalization and punctuation of model names.
Use shorter family names only after the full name is established.
Spell out a term on first use and put the acronym in parentheses unless the acronym is widely understood by the intended audience.
Use the acronym on later mentions after it has been defined.
For long documents, reintroduce the full term if readers might lose context.
Form plurals of acronyms with s, not an apostrophe, such as GPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such as CPU, GPU, PC, API, and UI usually do not need to be spelled out for developer audiences.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
**/*.{md,rst,html}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)

Link the first mention of a product name when the destination helps the reader.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
**/*.md

📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)

Documentation must be updated if activation or usage changed

**/*.md: Use title case consistently in technical documentation headings
Avoid quotation marks, ampersands, and exclamation marks in headings
Keep product, event, research, and whitepaper names in their official title case
Use title case for table headers
Do not force social-media sentence case into technical docs
Format code elements, commands, parameters, package names, and expressions in monospace
Format directories, file names, and paths in monospace using backticks
Use angle brackets inside monospace for variables inside paths, such as /home/<username>/.login
Format error messages and strings in quotation marks, keeping literal code strings in code formatting when clearer
Format UI buttons, menus, fields, and labels in bold
Use angle brackets between UI labels for menu paths, such as File > Save As
Use italics for new terms on first use, sparingly and only when introducing the term
Use italics for publication titles
Format keyboard shortcuts in plain text, such as Press Ctrl+Alt+Delete
Use owner/repo link text for GitHub repositories, preferring [NVIDIA/NeMo](link) over prose references like 'the GitHub repo'
Introduce every code block with a complete sentence
Do not make a code block complete the grammar of the previous sentence
Do not continue a sentence after a code block
Use syntax highlighting when the format supports it for code blocks
Avoid the word 'snippet' unless the surrounding docs already use it as a term of art
Keep inline method, function, and class references consistent with nearby docs, omitting empty parentheses for prose readability when no call is shown
Use descriptive anchor text that matches the destination title when possible for links
Avoid raw URLs in running text
Avoid generic anchor text such as 'here,' 'this page,' and 'read more'
Include acronyms in link text when a linked term includes an acronym
Do not link long sentences or multiple sentences
Avoid links ...

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
**/{docs,examples,**/*.md,*.patch,*.diff,.github,*.sh,*.yaml,*.yml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update documentation, examples, CI configuration, and patch artifacts when performing rename operations

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
**/*.{md,rst,txt}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)

Spell NVIDIA in all caps. Do not use Nvidia, nvidia, or NV.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
**/*.{md,rst}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)

**/*.{md,rst}: Format commands, code elements, expressions, package names, file names, and paths as inline code.
Use descriptive link text. Avoid raw URLs and weak anchors such as "here" or "read more."
Use title case consistently for technical documentation headings.
Introduce code blocks, lists, tables, and images with complete sentences.
Write procedures as imperative steps. Keep steps parallel and split long procedures into smaller tasks.
Prefer active voice, present tense, short sentences, contractions, and plain English.
Use can for possibility and reserve may for permission.
Use after for temporal relationships instead of once.
Prefer refer to over see when the wording points readers to another resource.
Avoid culture-specific idioms, unnecessary Latinisms, jokes, and marketing exaggeration in technical docs.
Spell out months in body text, avoid ordinal dates, and use clear time zones.
Spell out whole numbers from zero through nine unless they are technical values, parameters, versions, or UI values.
Use numerals for 10 or greater and include commas in thousands.
Do not add trademark symbols to learning-oriented docs unless the source, platform, or legal guidance explicitly requires them.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run docs link validation with just docs-linkcheck when links change

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
  • python/nemo_relay/plugin.py
  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • python/tests/test_plugin_config.py
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • crates/wasm/wrappers/esm/index.js
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
  • python/nemo_relay/plugin.py
  • crates/node/plugin.js
  • crates/core/src/plugin.rs
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/src/api/mod.rs
  • crates/node/plugin.d.ts
  • crates/ffi/src/api/mod.rs
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/src/launcher.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/coverage/server_tests.rs
  • go/nemo_relay/plugin_gap_test.go
  • crates/cli/tests/cli_tests.rs
  • crates/wasm/wrappers/esm/plugin.js
  • go/nemo_relay/plugin.go
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/src/server.rs
  • crates/cli/src/doctor.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • python/tests/test_plugin_config.py
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
**/SKILL.md

📄 CodeRabbit inference engine (AGENTS.md)

SKILL.md files are skill entrypoints and do not need SPDX headers, but they must always start with YAML frontmatter containing at least name and description.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md

⚙️ CodeRabbit configuration file

**/SKILL.md: Do not flag SKILL.md files for missing SPDX headers. Skill entrypoints intentionally start with YAML frontmatter instead.
Verify that every SKILL.md keeps valid YAML frontmatter with at least name and description fields before the Markdown body.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • skills/nemo-relay-tune-adaptive-config/SKILL.md
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/wasm/wrappers/esm/index.js
  • crates/node/tests/plugin_tests.mjs
  • python/nemo_relay/plugin.py
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/src/api/mod.rs
  • crates/node/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/wasm/src/api/mod.rs
  • crates/wasm/tests-js/plugin_tests.mjs
  • crates/wasm/wrappers/esm/plugin.js
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/wasm/wrappers/esm/index.js
  • crates/node/tests/plugin_tests.mjs
  • python/nemo_relay/plugin.py
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/src/api/mod.rs
  • crates/node/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/wasm/src/api/mod.rs
  • go/nemo_relay/plugin_gap_test.go
  • crates/wasm/tests-js/plugin_tests.mjs
  • crates/wasm/wrappers/esm/plugin.js
  • go/nemo_relay/plugin.go
**/*.{wasm,js,ts}{,x}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Files:

  • crates/wasm/wrappers/esm/index.js
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/wasm/wrappers/esm/plugin.js
crates/wasm/{wrappers,tests-js,scripts}/**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/test-wasm-binding/SKILL.md)

Format changed WebAssembly JS/TS wrapper files with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/index.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/wasm/wrappers/esm/plugin.js
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run Node.js formatting with npm run format --workspace=nemo-relay-node

Include SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax

Files:

  • crates/wasm/wrappers/esm/index.js
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/wasm/wrappers/esm/plugin.js
crates/wasm/**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run WebAssembly formatting with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/index.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/wasm/wrappers/esm/plugin.js
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • crates/wasm/wrappers/esm/index.js
  • python/nemo_relay/plugin.py
  • crates/node/plugin.js
  • crates/core/src/plugin.rs
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/src/api/mod.rs
  • crates/node/plugin.d.ts
  • crates/ffi/src/api/mod.rs
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/src/launcher.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/coverage/server_tests.rs
  • go/nemo_relay/plugin_gap_test.go
  • crates/cli/tests/cli_tests.rs
  • crates/wasm/wrappers/esm/plugin.js
  • go/nemo_relay/plugin.go
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/src/server.rs
  • crates/cli/src/doctor.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • python/tests/test_plugin_config.py
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/wasm/wrappers/esm/index.js
  • crates/node/tests/plugin_tests.mjs
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/ffi/nemo_relay.h
  • crates/node/src/api/mod.rs
  • crates/node/plugin.d.ts
  • crates/ffi/src/api/mod.rs
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/wasm/src/api/mod.rs
  • crates/wasm/tests-js/plugin_tests.mjs
  • crates/wasm/wrappers/esm/plugin.js
  • crates/ffi/src/api/plugin.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.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/node/tests/plugin_tests.mjs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • go/nemo_relay/plugin_gap_test.go
  • crates/cli/tests/cli_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • python/tests/test_plugin_config.py
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/tests/coverage/config_tests.rs
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Python native binding in crates/python/src/py_api/mod.rs with Python wrapper docstring in python/nemo_relay/<module>.py and type stubs in python/nemo_relay/*.pyi modules

Files:

  • python/nemo_relay/plugin.py
  • python/nemo_relay/plugin.pyi
  • python/nemo_relay/_native.pyi
python/nemo_relay/**/*.py

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Python identifiers (e.g., nemo_relay.tools.call)

Format changed Python wrapper and test files with uv run ruff format python

Python wrapper modules live under python/nemo_relay/; the native extension is built from crates/python with maturin.

Files:

  • python/nemo_relay/plugin.py
{python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,**/node/adaptive/**,**/wasm/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Ensure typed helper constructors still map cleanly to the same config document in adaptive bindings across Python, Go, Node, and WebAssembly

Files:

  • python/nemo_relay/plugin.py
{pyproject.toml,**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Python package names in pyproject.toml and import paths used throughout the codebase

Files:

  • python/nemo_relay/plugin.py
  • python/tests/test_plugin_config.py
**/*.{py,txt,toml,cfg,yaml,yml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Python package names and top-level module imports during coordinated rename operations

Files:

  • python/nemo_relay/plugin.py
  • python/tests/test_plugin_config.py
**/*.py

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.py: Run Python formatting with uv run ruff format python
Run Python testing with uv run pytest -k "<pattern>"

**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Run ty for Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code with uv run pre-commit run --all-files to enforce Ruff linting and formatting, and ty type checking

Files:

  • python/nemo_relay/plugin.py
  • python/tests/test_plugin_config.py
python/nemo_relay/**/*

⚙️ CodeRabbit configuration file

python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/nemo_relay/plugin.py
  • python/nemo_relay/plugin.pyi
  • python/nemo_relay/_native.pyi
crates/node/**/*.{js,ts,jsx,tsx,json}

📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)

Format changed Node files with npm run format --workspace=nemo-relay-node

Files:

  • crates/node/plugin.js
  • crates/node/plugin.d.ts
crates/node/**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js public entry points include the main runtime package plus nemo-relay-node/typed, nemo-relay-node/plugin, and nemo-relay-node/adaptive.

Files:

  • crates/node/plugin.js
  • crates/node/plugin.d.ts
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/core/src/plugin.rs
  • crates/node/src/api/mod.rs
  • crates/ffi/src/api/mod.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/src/launcher.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/tests/cli_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/src/server.rs
  • crates/cli/src/doctor.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
**/{Cargo.toml,**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/src/plugin.rs
  • crates/node/src/api/mod.rs
  • crates/ffi/src/api/mod.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/src/launcher.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/tests/cli_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/src/server.rs
  • crates/cli/src/doctor.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
**/*.{h,hpp,c,cpp,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/src/plugin.rs
  • crates/ffi/nemo_relay.h
  • crates/node/src/api/mod.rs
  • crates/ffi/src/api/mod.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/src/launcher.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/tests/cli_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/src/server.rs
  • crates/cli/src/doctor.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugin_tests.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/src/plugin.rs
  • crates/node/src/api/mod.rs
  • crates/ffi/src/api/mod.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/src/launcher.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/tests/cli_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/src/server.rs
  • crates/cli/src/doctor.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugin_tests.rs
crates/{core,adaptive}/**

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Files:

  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugin_tests.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/core/src/plugin.rs
  • crates/node/src/api/mod.rs
  • crates/ffi/src/api/mod.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/src/launcher.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/tests/cli_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/src/server.rs
  • crates/cli/src/doctor.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugin_tests.rs
{docs/**,README.md,CONTRIBUTING.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,examples/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

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.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
{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/observability-plugin/atof.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{h,c}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update C header names and symbol prefixes during coordinated rename operations

Files:

  • crates/ffi/nemo_relay.h
crates/ffi/**

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Rebuild the FFI crate in release mode so the shared library and header stay in sync when making changes to crates/ffi

Files:

  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/mod.rs
  • crates/ffi/src/api/plugin.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
crates/ffi/nemo_relay.h

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Check the generated header diff when any exported symbol or type changed in the FFI surface

Ensure FFI header sync for crates/ffi/nemo_relay.h through Cargo/build.rs

Files:

  • crates/ffi/nemo_relay.h
crates/ffi/*.h

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Prefix C FFI exports with nemo_relay_

Files:

  • crates/ffi/nemo_relay.h
crates/node/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Node.js binding in crates/node/src/api/mod.rs for language-native bindings

Files:

  • crates/node/src/api/mod.rs
crates/node/src/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use camelCase naming convention for Node.js identifiers (e.g., toolCall)

Files:

  • crates/node/src/api/mod.rs
crates/node/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)

Use npm run check:docstrings --workspace=nemo-relay-node to validate public API docstring checks when surface docs changed

Files:

  • crates/node/plugin.d.ts
crates/ffi/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

crates/ffi/src/api/**/*.rs: Add or update FFI wrappers in relevant crates/ffi/src/api/*.rs modules, re-export through crates/ffi/src/api/mod.rs, and ensure generated crates/ffi/nemo_relay.h stays correct
Use nemo_relay_ prefix for C FFI function names (e.g., nemo_relay_tool_call)

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/src/api/plugin.rs
crates/ffi/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/ffi, also use test-ffi-surface for validation

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/src/api/plugin.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • go/nemo_relay/plugin_gap_test.go
  • crates/cli/tests/cli_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/gateway_tests.rs
  • python/tests/test_plugin_config.py
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/cli/tests/coverage/session_tests.rs
  • crates/cli/tests/coverage/config_tests.rs
crates/wasm/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update WebAssembly binding in crates/wasm/src/api/mod.rs for language-native bindings

Files:

  • crates/wasm/src/api/mod.rs
crates/wasm/src/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use camelCase naming convention for WebAssembly identifiers (e.g., toolCall)

Files:

  • crates/wasm/src/api/mod.rs
crates/wasm/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-wasm-binding/SKILL.md)

Run cargo test -p nemo-relay-wasm when Rust-only WebAssembly helpers changed

Files:

  • crates/wasm/src/api/mod.rs
go/nemo_relay/**/*.go

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Go wrapper in go/nemo_relay/nemo_relay.go with doc comment and shorthand package if the capability belongs there

go/nemo_relay/**/*.go: Format changed Go packages with cd go/nemo_relay && go fmt ./...
Run Go tests with just test-go to build and test the NeMo Relay Go binding
Use just build-go when you want an explicit build-only pass or need the artifact for other work
Use just ci=true test-go when you need the CI-style coverage and JUnit path
On macOS, set DYLD_LIBRARY_PATH to the ../../target/release directory before running the raw go test command directly

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
go/**/*.go

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use PascalCase naming convention for Go identifiers (e.g., nemo_relay.ToolCall)

Run Go formatting with cd go/nemo_relay && go fmt ./...

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
{go/nemo_relay/go.mod,go/**/*.go}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure Go module path in go/nemo_relay/go.mod matches import statements in Go source files

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
**/*.go

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Go module paths and package paths during coordinated rename operations

**/*.go: Use gofmt for Go code formatting
Run go vet ./... for Go static analysis
Use Go PascalCase naming convention for Go identifiers
Include SPDX license header in all Go source files using double-slash comment syntax
Validate Go code with uv run pre-commit run --all-files to enforce gofmt formatting and go vet static analysis

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
go/nemo_relay/**/*

⚙️ CodeRabbit configuration file

go/nemo_relay/**/*: Review Go binding changes for cgo memory ownership, race safety, callback cleanup, idiomatic exported APIs, and parity with Rust/FFI behavior.
Any API change should include focused Go tests and consider race-test behavior.

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
**/test_*.{py,py}

📄 CodeRabbit inference engine (.agents/skills/add-integration/SKILL.md)

Relevant integration tests or smoke coverage must exist for the integration path

Files:

  • python/tests/test_plugin_config.py
**/*config*.{rs,ts,py,go,js,json,yaml,yml}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Ensure dynamic config shape still matches the documented canonical model

Files:

  • python/tests/test_plugin_config.py
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/config_tests.rs
python/**/*test*.py

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

python/**/*test*.py: Do not add @pytest.mark.asyncio to any test in Python test files
Do not add a -> None return type annotation to test functions
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock with the spec constructor argument when necessary, rather than defining a new class
Prefix mocked class names with mock, not fake
Prefer pytest fixtures over helper methods in Python tests
Prefer pytest.mark.parametrize over creating individual tests for different input types

Files:

  • python/tests/test_plugin_config.py
python/**/{conftest.py,*test*.py}

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

When creating a fixture follow the pattern: @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) def <fixture_name>_fixture() -> <return_type>: and only specify the scope argument when the value is something other than "function"

Files:

  • python/tests/test_plugin_config.py
crates/python/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

If the native Rust bridge changed, add the Rust crate tests for nemo-relay-python

Files:

  • crates/python/src/py_plugin.rs
🧠 Learnings (1)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/plugin.d.ts
🔇 Additional comments (12)
crates/ffi/src/api/plugin.rs (1)

12-18: LGTM!

Also applies to: 129-155

crates/node/tests/plugin_tests.mjs (1)

9-13: LGTM!

crates/wasm/tests-js/plugin_tests.mjs (1)

18-22: LGTM!

crates/wasm/wrappers/esm/index.js (1)

43-43: LGTM!

go/nemo_relay/plugin.go (1)

28-28: LGTM!

Also applies to: 94-112, 263-278, 588-598

crates/wasm/src/api/mod.rs (1)

2167-2178: LGTM!

crates/node/plugin.d.ts (1)

164-176: LGTM!

crates/node/plugin.js (1)

51-65: LGTM!

Also applies to: 175-179

python/nemo_relay/plugin.pyi (1)

111-111: LGTM!

crates/wasm/wrappers/esm/plugin.d.ts (1)

162-174: LGTM!

crates/wasm/wrappers/esm/plugin.js (1)

4-13: LGTM!

Also applies to: 54-68

crates/wasm/wrappers/nodejs/plugin.js (1)

6-15: LGTM!

Also applies to: 56-70, 179-181

Comment thread crates/core/src/plugin.rs
Comment thread crates/ffi/nemo_relay.h Outdated
Comment thread crates/ffi/tests/unit/api/plugin_tests.rs Outdated
Comment thread docs/observability-plugin/atof.mdx
Comment thread go/nemo_relay/plugin_gap_test.go Outdated
Comment thread python/nemo_relay/plugin.py Outdated
Comment thread python/tests/test_plugin_config.py Outdated
Copy link
Copy Markdown
Member

@willkill07 willkill07 left a comment

Choose a reason for hiding this comment

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

code-driven plugin configuration is accomplished through each language binding's plugin initialize function.

  1. I do not see the "base" layer being inferred automatically from user/project/global config (which was the entire point of layering).
  2. Providing per-language binding layering is nice, but I believe we can drop --plugin-config outright. Folks should be using the configuration files rather than ad-hoc.
  3. The added/improved error output is good!

Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@zhongxuanwang-nv zhongxuanwang-nv requested a review from a team as a code owner June 2, 2026 19:04
Copy link
Copy Markdown

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/wasm/wrappers/esm/plugin.d.ts (1)

175-185: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the declaration JSDoc to match the new optional semantics.

Line 180 still describes config as required, and the remarks do not mention the empty-base layering behavior that the JS wrapper now documents. Consumers relying on editor docs will get the wrong contract from this .d.ts.

🤖 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/wasm/wrappers/esm/plugin.d.ts` around lines 175 - 185, The JSDoc for
the exported initialize function is out of sync with its new optional semantics:
update the `@param` description for initialize(config?: PluginConfig | null) to
indicate that config is optional (may be omitted or null) and describe the
empty-base layering behavior (that an omitted/null config will activate using
the empty/base layer and that partial registration is rolled back on failure);
also update `@remarks` to mention the empty-base layering behavior and the
optional nature so editor tooltips reflect the correct contract (refer to the
initialize function, PluginConfig type, and returned ConfigReport).
♻️ Duplicate comments (1)
crates/ffi/src/api/plugin.rs (1)

129-136: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Document out_json ownership in the source docs.

Both APIs allocate a JSON string and write it through out_json, but the Rust docs still do not say that callers own *out_json and must free it with nemo_relay_string_free. Because crates/ffi/nemo_relay.h is generated from these comments, the omission leaks into the public C ABI docs.

📝 Proposed doc fix
 /// Validate a generic plugin config document and return the diagnostics report as JSON.
+///
+/// On success, writes an allocated JSON string to `out_json`. The caller must
+/// free `*out_json` with `nemo_relay_string_free`.
 ///
 /// # Safety
 /// `config_json` must be a valid C string and `out_json` must be a valid, non-null pointer.
@@
 /// Initialize plugins from discovered config files plus an optional code overlay.
+///
+/// On success, writes an allocated JSON string to `out_json`. The caller must
+/// free `*out_json` with `nemo_relay_string_free`.
 ///
 /// # Safety
 /// `config_json` may be null to use only discovered file config. When non-null, it must be a valid

Also applies to: 168-176

🤖 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/ffi/src/api/plugin.rs` around lines 129 - 136, Update the function
docs for nemo_relay_validate_plugin_config (and the similar API around lines
168-176) to explicitly state that the function allocates a NUL-terminated C
string, writes the pointer to the caller-provided out_json, and that the caller
takes ownership of *out_json and must free it using nemo_relay_string_free;
mention the same ownership/cleanup requirement in the # Safety section so the
generated C header (nemo_relay.h) documents the ownership clearly.
🤖 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/tests/coverage/server_tests.rs`:
- Around line 447-448: Remove the duplicated assertion in the test: there are
two identical lines asserting error.to_string().contains("plugins.toml
/tmp/plugins.toml"); delete one of these duplicate assert! calls so the test
only checks that condition once.

In `@crates/ffi/tests/unit/api/plugin_tests.rs`:
- Around line 55-58: The test calling
nemo_relay_initialize_plugins_from_discovered_config is not hermetic because it
reads from the current working directory and XDG/HOME locations; before calling
nemo_relay_initialize_plugins_from_discovered_config (the assertion around
init_json), create a temporary directory (e.g., via tempfile::tempdir()), set
std::env::set_current_dir to that temp dir, and override XDG_CONFIG_HOME and
HOME with fresh temp dir paths using std::env::set_var so that the function
cannot see ambient ~/.nemo-relay/plugins.toml; ensure the temporary dirs are
kept alive for the duration of the test and restored/cleaned up (or env vars
reset) after the test so init_json/assertion runs deterministically.

In `@crates/node/tests/plugin_tests.mjs`:
- Around line 12-71: Add a new test in plugin_tests.mjs that calls
plugin.initialize() with no arguments to exercise the zero-argument code path
and ensure the repo-level plugins.toml is still honored; reuse the existing temp
project setup (root/project/.nemo-relay/plugins.toml) and the same process.cwd /
env manipulation as the current test, then assert the same failure/behavior
(e.g., rejects with /filename_template/ or the expected outcome) and finally
call plugin.clear() and restore env/cwd in a finally block to match cleanup
semantics of the existing test.

In `@docs/build-plugins/plugin-configuration-files.mdx`:
- Around line 85-88: The documentation uses the concrete name
plugin.initialize(...) which is not a universal API across bindings (Rust uses
initialize_plugins_from_discovered_config(...)); update the sentence to avoid
implying a single public method by replacing the concrete call with a
binding-agnostic phrase like “the binding-specific plugin initialization helper”
and, if helpful, add parenthetical examples for specific bindings (e.g.,
plugin.initialize(...) for JS/TS, initialize_plugins_from_discovered_config(...)
for Rust) so readers know the analogous entry points without asserting a single
API name.

---

Outside diff comments:
In `@crates/wasm/wrappers/esm/plugin.d.ts`:
- Around line 175-185: The JSDoc for the exported initialize function is out of
sync with its new optional semantics: update the `@param` description for
initialize(config?: PluginConfig | null) to indicate that config is optional
(may be omitted or null) and describe the empty-base layering behavior (that an
omitted/null config will activate using the empty/base layer and that partial
registration is rolled back on failure); also update `@remarks` to mention the
empty-base layering behavior and the optional nature so editor tooltips reflect
the correct contract (refer to the initialize function, PluginConfig type, and
returned ConfigReport).

---

Duplicate comments:
In `@crates/ffi/src/api/plugin.rs`:
- Around line 129-136: Update the function docs for
nemo_relay_validate_plugin_config (and the similar API around lines 168-176) to
explicitly state that the function allocates a NUL-terminated C string, writes
the pointer to the caller-provided out_json, and that the caller takes ownership
of *out_json and must free it using nemo_relay_string_free; mention the same
ownership/cleanup requirement in the # Safety section so the generated C header
(nemo_relay.h) documents the ownership clearly.
🪄 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: c058a066-6936-48db-938b-aba03fc1856a

📥 Commits

Reviewing files that changed from the base of the PR and between 64508db and 75bc17f.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (35)
  • crates/cli/src/config.rs
  • crates/cli/src/installer.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/mod.rs
  • crates/ffi/src/api/plugin.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/node/plugin.d.ts
  • crates/node/plugin.js
  • crates/node/src/api/mod.rs
  • crates/node/tests/plugin_tests.mjs
  • crates/python/src/py_plugin.rs
  • crates/wasm/src/api/mod.rs
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/esm/plugin.js
  • crates/wasm/wrappers/nodejs/plugin.js
  • docs/build-plugins/plugin-configuration-files.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/nemo-relay-cli/basic-usage.mdx
  • go/nemo_relay/plugin.go
  • go/nemo_relay/plugin_gap_test.go
  • python/nemo_relay/_native.pyi
  • python/nemo_relay/plugin.py
  • python/nemo_relay/plugin.pyi
  • python/tests/test_plugin_config.py
  • skills/nemo-relay-build-plugin/SKILL.md
💤 Files with no reviewable changes (3)
  • crates/cli/src/installer.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (71)
**/{Cargo.toml,**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/Cargo.toml
  • crates/ffi/src/api/mod.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/core/src/plugin.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • crates/ffi/src/api/mod.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/core/src/plugin.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
**/*.{py,txt,toml,cfg,yaml,yml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Python package names and top-level module imports during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • python/tests/test_plugin_config.py
  • python/nemo_relay/plugin.py
**/Cargo.toml

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update WebAssembly crate names and generated package names during coordinated rename operations

Confirm or infer the target release version from upstream/main:Cargo.toml. Derive the release branch as release/<major>.<minor>.

Files:

  • crates/core/Cargo.toml
crates/{core,adaptive}/**

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • crates/core/Cargo.toml
  • skills/nemo-relay-build-plugin/SKILL.md
  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current

Files:

  • crates/core/Cargo.toml
  • skills/nemo-relay-build-plugin/SKILL.md
  • docs/nemo-relay-cli/basic-usage.mdx
  • python/tests/test_plugin_config.py
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
  • python/nemo_relay/plugin.py
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in TOML configuration files using hash comment syntax

Files:

  • crates/core/Cargo.toml
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • crates/core/Cargo.toml
  • crates/ffi/src/api/mod.rs
  • skills/nemo-relay-build-plugin/SKILL.md
  • crates/wasm/wrappers/esm/plugin.js
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/node/plugin.js
  • go/nemo_relay/plugin_gap_test.go
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/wasm/wrappers/esm/plugin.d.ts
  • go/nemo_relay/plugin.go
  • crates/cli/tests/coverage/server_tests.rs
  • python/tests/test_plugin_config.py
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/core/src/plugin.rs
  • crates/ffi/src/api/plugin.rs
  • crates/node/plugin.d.ts
  • python/nemo_relay/plugin.py
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
crates/ffi/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

crates/ffi/src/api/**/*.rs: Add or update FFI wrappers in relevant crates/ffi/src/api/*.rs modules, re-export through crates/ffi/src/api/mod.rs, and ensure generated crates/ffi/nemo_relay.h stays correct
Use nemo_relay_ prefix for C FFI function names (e.g., nemo_relay_tool_call)

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/src/api/plugin.rs
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/core/src/plugin.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
**/*.{h,hpp,c,cpp,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/core/src/plugin.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
crates/ffi/**

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Rebuild the FFI crate in release mode so the shared library and header stay in sync when making changes to crates/ffi

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/plugin.rs
crates/ffi/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/ffi, also use test-ffi-surface for validation

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • crates/ffi/src/api/mod.rs
  • crates/wasm/wrappers/esm/plugin.js
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/node/plugin.js
  • go/nemo_relay/plugin_gap_test.go
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/wasm/wrappers/esm/plugin.d.ts
  • go/nemo_relay/plugin.go
  • crates/cli/tests/coverage/server_tests.rs
  • python/tests/test_plugin_config.py
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/core/src/plugin.rs
  • crates/ffi/src/api/plugin.rs
  • crates/node/plugin.d.ts
  • python/nemo_relay/plugin.py
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/ffi/src/api/mod.rs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/python/src/py_plugin.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/core/src/plugin.rs
  • crates/ffi/src/api/plugin.rs
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/ffi/src/api/mod.rs
  • crates/node/tests/plugin_tests.mjs
  • crates/wasm/wrappers/esm/plugin.js
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/node/plugin.js
  • crates/python/src/py_plugin.rs
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/ffi/src/api/plugin.rs
  • crates/node/plugin.d.ts
**/*.{md,rst,html,txt}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)

**/*.{md,rst,html,txt}: Always spell NVIDIA in all caps. Do not use Nvidia, nvidia, nVidia, nVIDIA, or NV.
Use an NVIDIA before a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol after NVIDIA when referring to the company.
Use trademark symbols with product names only when the document type or legal guidance requires them.
Verify official capitalization, spacing, and hyphenation for product names.
Precede NVIDIA product names with NVIDIA on first mention when it is natural and accurate.
Do not rewrite product names for grammar or title-case rules.
Preserve third-party product names according to the owner's spelling.
Include the company name and full model qualifier on first use when it helps identify the model.
Preserve the official capitalization and punctuation of model names.
Use shorter family names only after the full name is established.
Spell out a term on first use and put the acronym in parentheses unless the acronym is widely understood by the intended audience.
Use the acronym on later mentions after it has been defined.
For long documents, reintroduce the full term if readers might lose context.
Form plurals of acronyms with s, not an apostrophe, such as GPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such as CPU, GPU, PC, API, and UI usually do not need to be spelled out for developer audiences.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
**/*.{md,rst,html}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)

Link the first mention of a product name when the destination helps the reader.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
**/*.md

📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)

Documentation must be updated if activation or usage changed

**/*.md: Use title case consistently in technical documentation headings
Avoid quotation marks, ampersands, and exclamation marks in headings
Keep product, event, research, and whitepaper names in their official title case
Use title case for table headers
Do not force social-media sentence case into technical docs
Format code elements, commands, parameters, package names, and expressions in monospace
Format directories, file names, and paths in monospace using backticks
Use angle brackets inside monospace for variables inside paths, such as /home/<username>/.login
Format error messages and strings in quotation marks, keeping literal code strings in code formatting when clearer
Format UI buttons, menus, fields, and labels in bold
Use angle brackets between UI labels for menu paths, such as File > Save As
Use italics for new terms on first use, sparingly and only when introducing the term
Use italics for publication titles
Format keyboard shortcuts in plain text, such as Press Ctrl+Alt+Delete
Use owner/repo link text for GitHub repositories, preferring [NVIDIA/NeMo](link) over prose references like 'the GitHub repo'
Introduce every code block with a complete sentence
Do not make a code block complete the grammar of the previous sentence
Do not continue a sentence after a code block
Use syntax highlighting when the format supports it for code blocks
Avoid the word 'snippet' unless the surrounding docs already use it as a term of art
Keep inline method, function, and class references consistent with nearby docs, omitting empty parentheses for prose readability when no call is shown
Use descriptive anchor text that matches the destination title when possible for links
Avoid raw URLs in running text
Avoid generic anchor text such as 'here,' 'this page,' and 'read more'
Include acronyms in link text when a linked term includes an acronym
Do not link long sentences or multiple sentences
Avoid links ...

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
**/{docs,examples,**/*.md,*.patch,*.diff,.github,*.sh,*.yaml,*.yml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update documentation, examples, CI configuration, and patch artifacts when performing rename operations

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
**/*.{md,rst,txt}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)

Spell NVIDIA in all caps. Do not use Nvidia, nvidia, or NV.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
**/*.{md,rst}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)

**/*.{md,rst}: Format commands, code elements, expressions, package names, file names, and paths as inline code.
Use descriptive link text. Avoid raw URLs and weak anchors such as "here" or "read more."
Use title case consistently for technical documentation headings.
Introduce code blocks, lists, tables, and images with complete sentences.
Write procedures as imperative steps. Keep steps parallel and split long procedures into smaller tasks.
Prefer active voice, present tense, short sentences, contractions, and plain English.
Use can for possibility and reserve may for permission.
Use after for temporal relationships instead of once.
Prefer refer to over see when the wording points readers to another resource.
Avoid culture-specific idioms, unnecessary Latinisms, jokes, and marketing exaggeration in technical docs.
Spell out months in body text, avoid ordinal dates, and use clear time zones.
Spell out whole numbers from zero through nine unless they are technical values, parameters, versions, or UI values.
Use numerals for 10 or greater and include commas in thousands.
Do not add trademark symbols to learning-oriented docs unless the source, platform, or legal guidance explicitly requires them.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run docs link validation with just docs-linkcheck when links change

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/SKILL.md

📄 CodeRabbit inference engine (AGENTS.md)

SKILL.md files are skill entrypoints and do not need SPDX headers, but they must always start with YAML frontmatter containing at least name and description.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md

⚙️ CodeRabbit configuration file

**/SKILL.md: Do not flag SKILL.md files for missing SPDX headers. Skill entrypoints intentionally start with YAML frontmatter instead.
Verify that every SKILL.md keeps valid YAML frontmatter with at least name and description fields before the Markdown body.

Files:

  • skills/nemo-relay-build-plugin/SKILL.md
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Python native binding in crates/python/src/py_api/mod.rs with Python wrapper docstring in python/nemo_relay/<module>.py and type stubs in python/nemo_relay/*.pyi modules

Files:

  • python/nemo_relay/plugin.pyi
  • python/nemo_relay/_native.pyi
  • python/nemo_relay/plugin.py
python/nemo_relay/**/*

⚙️ CodeRabbit configuration file

python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/nemo_relay/plugin.pyi
  • python/nemo_relay/_native.pyi
  • python/nemo_relay/plugin.py
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/node/tests/plugin_tests.mjs
  • crates/wasm/wrappers/esm/plugin.js
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/node/plugin.d.ts
  • python/nemo_relay/plugin.py
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/node/tests/plugin_tests.mjs
  • crates/wasm/wrappers/esm/plugin.js
  • crates/node/plugin.js
  • go/nemo_relay/plugin_gap_test.go
  • crates/wasm/wrappers/esm/plugin.d.ts
  • go/nemo_relay/plugin.go
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/node/src/api/mod.rs
  • crates/wasm/src/api/mod.rs
  • crates/node/plugin.d.ts
  • python/nemo_relay/plugin.py
{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/node/tests/plugin_tests.mjs
  • crates/ffi/tests/unit/api/plugin_tests.rs
  • go/nemo_relay/plugin_gap_test.go
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • python/tests/test_plugin_config.py
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/cli/tests/coverage/config_tests.rs
**/*.{wasm,js,ts}{,x}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Files:

  • crates/wasm/wrappers/esm/plugin.js
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/node/plugin.d.ts
crates/wasm/{wrappers,tests-js,scripts}/**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/test-wasm-binding/SKILL.md)

Format changed WebAssembly JS/TS wrapper files with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run Node.js formatting with npm run format --workspace=nemo-relay-node

Include SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax

Files:

  • crates/wasm/wrappers/esm/plugin.js
  • crates/node/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
  • crates/node/plugin.d.ts
crates/wasm/**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run WebAssembly formatting with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/plugin.js
  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/wasm/wrappers/nodejs/plugin.js
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/ffi/tests/unit/api/plugin_tests.rs
  • go/nemo_relay/plugin_gap_test.go
  • crates/core/tests/unit/plugin_tests.rs
  • crates/cli/tests/coverage/doctor_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • python/tests/test_plugin_config.py
  • crates/cli/tests/cli_tests.rs
  • crates/cli/tests/coverage/installer_tests.rs
  • crates/cli/tests/coverage/config_tests.rs
**/*.{h,c}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update C header names and symbol prefixes during coordinated rename operations

Files:

  • crates/ffi/nemo_relay.h
crates/ffi/nemo_relay.h

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Check the generated header diff when any exported symbol or type changed in the FFI surface

Ensure FFI header sync for crates/ffi/nemo_relay.h through Cargo/build.rs

Files:

  • crates/ffi/nemo_relay.h
crates/ffi/*.h

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Prefix C FFI exports with nemo_relay_

Files:

  • crates/ffi/nemo_relay.h
crates/node/**/*.{js,ts,jsx,tsx,json}

📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)

Format changed Node files with npm run format --workspace=nemo-relay-node

Files:

  • crates/node/plugin.js
  • crates/node/plugin.d.ts
crates/node/**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js public entry points include the main runtime package plus nemo-relay-node/typed, nemo-relay-node/plugin, and nemo-relay-node/adaptive.

Files:

  • crates/node/plugin.js
  • crates/node/plugin.d.ts
go/nemo_relay/**/*.go

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Go wrapper in go/nemo_relay/nemo_relay.go with doc comment and shorthand package if the capability belongs there

go/nemo_relay/**/*.go: Format changed Go packages with cd go/nemo_relay && go fmt ./...
Run Go tests with just test-go to build and test the NeMo Relay Go binding
Use just build-go when you want an explicit build-only pass or need the artifact for other work
Use just ci=true test-go when you need the CI-style coverage and JUnit path
On macOS, set DYLD_LIBRARY_PATH to the ../../target/release directory before running the raw go test command directly

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
go/**/*.go

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use PascalCase naming convention for Go identifiers (e.g., nemo_relay.ToolCall)

Run Go formatting with cd go/nemo_relay && go fmt ./...

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
{go/nemo_relay/go.mod,go/**/*.go}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure Go module path in go/nemo_relay/go.mod matches import statements in Go source files

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
**/*.go

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Go module paths and package paths during coordinated rename operations

**/*.go: Use gofmt for Go code formatting
Run go vet ./... for Go static analysis
Use Go PascalCase naming convention for Go identifiers
Include SPDX license header in all Go source files using double-slash comment syntax
Validate Go code with uv run pre-commit run --all-files to enforce gofmt formatting and go vet static analysis

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
go/nemo_relay/**/*

⚙️ CodeRabbit configuration file

go/nemo_relay/**/*: Review Go binding changes for cgo memory ownership, race safety, callback cleanup, idiomatic exported APIs, and parity with Rust/FFI behavior.
Any API change should include focused Go tests and consider race-test behavior.

Files:

  • go/nemo_relay/plugin_gap_test.go
  • go/nemo_relay/plugin.go
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
crates/python/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

If the native Rust bridge changed, add the Rust crate tests for nemo-relay-python

Files:

  • crates/python/src/py_plugin.rs
{docs/**,README.md,CONTRIBUTING.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,examples/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

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.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/nemo-relay-cli/basic-usage.mdx
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
{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
  • docs/build-plugins/register-behavior.mdx
  • docs/build-plugins/plugin-configuration-files.mdx
**/test_*.{py,py}

📄 CodeRabbit inference engine (.agents/skills/add-integration/SKILL.md)

Relevant integration tests or smoke coverage must exist for the integration path

Files:

  • python/tests/test_plugin_config.py
**/*config*.{rs,ts,py,go,js,json,yaml,yml}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Ensure dynamic config shape still matches the documented canonical model

Files:

  • python/tests/test_plugin_config.py
  • crates/cli/tests/coverage/config_tests.rs
  • crates/cli/src/config.rs
{pyproject.toml,**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Python package names in pyproject.toml and import paths used throughout the codebase

Files:

  • python/tests/test_plugin_config.py
  • python/nemo_relay/plugin.py
python/**/*test*.py

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

python/**/*test*.py: Do not add @pytest.mark.asyncio to any test in Python test files
Do not add a -> None return type annotation to test functions
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock with the spec constructor argument when necessary, rather than defining a new class
Prefix mocked class names with mock, not fake
Prefer pytest fixtures over helper methods in Python tests
Prefer pytest.mark.parametrize over creating individual tests for different input types

Files:

  • python/tests/test_plugin_config.py
python/**/{conftest.py,*test*.py}

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

When creating a fixture follow the pattern: @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) def <fixture_name>_fixture() -> <return_type>: and only specify the scope argument when the value is something other than "function"

Files:

  • python/tests/test_plugin_config.py
**/*.py

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.py: Run Python formatting with uv run ruff format python
Run Python testing with uv run pytest -k "<pattern>"

**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Run ty for Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code with uv run pre-commit run --all-files to enforce Ruff linting and formatting, and ty type checking

Files:

  • python/tests/test_plugin_config.py
  • python/nemo_relay/plugin.py
crates/node/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Node.js binding in crates/node/src/api/mod.rs for language-native bindings

Files:

  • crates/node/src/api/mod.rs
crates/node/src/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use camelCase naming convention for Node.js identifiers (e.g., toolCall)

Files:

  • crates/node/src/api/mod.rs
crates/wasm/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update WebAssembly binding in crates/wasm/src/api/mod.rs for language-native bindings

Files:

  • crates/wasm/src/api/mod.rs
crates/wasm/src/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use camelCase naming convention for WebAssembly identifiers (e.g., toolCall)

Files:

  • crates/wasm/src/api/mod.rs
crates/wasm/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-wasm-binding/SKILL.md)

Run cargo test -p nemo-relay-wasm when Rust-only WebAssembly helpers changed

Files:

  • crates/wasm/src/api/mod.rs
crates/node/**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.agents/skills/test-node-binding/SKILL.md)

Use npm run check:docstrings --workspace=nemo-relay-node to validate public API docstring checks when surface docs changed

Files:

  • crates/node/plugin.d.ts
python/nemo_relay/**/*.py

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Python identifiers (e.g., nemo_relay.tools.call)

Format changed Python wrapper and test files with uv run ruff format python

Python wrapper modules live under python/nemo_relay/; the native extension is built from crates/python with maturin.

Files:

  • python/nemo_relay/plugin.py
{python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,**/node/adaptive/**,**/wasm/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Ensure typed helper constructors still map cleanly to the same config document in adaptive bindings across Python, Go, Node, and WebAssembly

Files:

  • python/nemo_relay/plugin.py
🧠 Learnings (1)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • crates/wasm/wrappers/esm/plugin.d.ts
  • crates/node/plugin.d.ts
🪛 Ruff (0.15.15)
python/tests/test_plugin_config.py

[warning] 15-15: Unused method argument: context

(ARG002)

🔇 Additional comments (18)
python/nemo_relay/plugin.py (1)

320-321: Preserve explicit None values in the overlay path.

Line 320 still routes the overlay through _normalize_object(config), which drops dict entries set to None. That means initialize(...) cannot clear a discovered value to JSON null, so the new layering API still loses explicit null overrides.

crates/node/src/api/mod.rs (1)

43-50: LGTM!

Also applies to: 3270-3277

crates/python/src/py_plugin.rs (1)

29-33: LGTM!

Also applies to: 755-772, 817-824

python/nemo_relay/_native.pyi (1)

2109-2122: LGTM!

python/nemo_relay/plugin.pyi (1)

112-114: LGTM!

python/tests/test_plugin_config.py (1)

7-17: LGTM!

Also applies to: 19-70

crates/wasm/src/api/mod.rs (1)

2828-2842: ⚡ Quick win

Expose initializePlugins overlay config as optional/nullable in WASM typings

initialize_plugins treats null/undefined as “no overlay” (None), but the exported wasm-bindgen parameter still declares unchecked_param_type = "Json" with config: JsValue, so generated JS/TS typings will likely keep initializePlugins’s config argument non-null. Align the wasm-bindgen parameter typing (and Rust parameter type if needed) to match the nullable runtime behavior.

Suggested fix
 #[wasm_bindgen(js_name = "initializePlugins", unchecked_return_type = "Json")]
  /// Validate and activate a plugin configuration.
  ///
  /// Uses discovered file config as the base where the target supports
  /// discovery, layers the supplied code config on top, replaces the current
  /// active plugin configuration, and rolls back partial registration on failure.
  pub async fn initialize_plugins(
-    #[wasm_bindgen(unchecked_param_type = "Json")] config: JsValue,
+    #[wasm_bindgen(unchecked_param_type = "Json | null | undefined")] config: Option<JsValue>,
  ) -> Result<JsValue, JsValue> {
      ensure_adaptive_component_registered()?;
-    let config = if config.is_null() || config.is_undefined() {
-        None
-    } else {
-        Some(js_to_json(&config)?)
-    };
+    let config = match config {
+        Some(value) if !value.is_null() && !value.is_undefined() => Some(js_to_json(&value)?),
+        _ => None,
+    };
      let report = initialize_plugins_from_discovered_config_impl(config)
          .await
          .map_err(to_js_err)?;
      serde_wasm_bindgen::to_value(&report).map_err(|e| JsValue::from_str(&e.to_string()))
  }
crates/node/plugin.d.ts (1)

182-189: LGTM!

crates/node/plugin.js (1)

72-80: LGTM!

crates/wasm/wrappers/esm/plugin.js (1)

74-82: LGTM!

crates/wasm/wrappers/nodejs/plugin.js (1)

76-84: LGTM!

crates/core/src/plugin.rs (1)

182-194: Duplicate same-kind overlays are still lossy.

Merging each overlay component into the first base entry with the same kind still collapses valid multi-instance configs when allows_multiple_components() is true. A code-driven overlay with two "kind": "x" components cannot target two existing "x" instances deterministically, so later instances are silently rewritten or ignored across every binding that calls this resolver.

crates/cli/src/config.rs (2)

310-316: LGTM!


435-436: LGTM!

Also applies to: 447-447, 457-457, 475-476, 764-764

crates/cli/tests/coverage/config_tests.rs (1)

44-44: LGTM!

Also applies to: 64-99, 560-560, 606-606, 617-617, 651-651, 739-739, 762-762

crates/cli/tests/cli_tests.rs (1)

309-370: LGTM!

Also applies to: 372-385

crates/cli/tests/coverage/doctor_tests.rs (1)

660-679: LGTM!

crates/cli/tests/coverage/installer_tests.rs (1)

117-117: LGTM!

Comment thread crates/cli/tests/coverage/server_tests.rs Outdated
Comment thread crates/ffi/tests/unit/api/plugin_tests.rs
Comment thread crates/node/tests/plugin_tests.mjs Outdated
Comment thread docs/build-plugins/plugin-configuration-files.mdx
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@zhongxuanwang-nv zhongxuanwang-nv marked this pull request as ready for review June 2, 2026 20:52
Copy link
Copy Markdown

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/node/tests/plugin_tests.mjs`:
- Around line 40-55: The finally block currently runs plugin.clear() first so if
plugin.clear() throws the rest of the cleanup (process.chdir(oldCwd), restoring
process.env.XDG_CONFIG_HOME/HOME, and fs.rmSync(root)) is skipped; change it so
each cleanup step runs regardless of others by isolating plugin.clear() in its
own try/catch (or by catching errors from plugin.clear()) and then always
restoring CWD/env and removing the temp dir—refer to plugin.clear(),
process.chdir(oldCwd), oldXdg/oldHome env restores, and fs.rmSync(root) to
ensure errors from plugin.clear() are logged/ignored but do not prevent the
remaining cleanup from executing.
🪄 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: 649bc5a6-aa27-4b58-a1e8-a198928b30d1

📥 Commits

Reviewing files that changed from the base of the PR and between 75bc17f and cf19861.

📒 Files selected for processing (7)
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/plugin.rs
  • crates/node/tests/plugin_tests.mjs
  • docs/build-plugins/plugin-configuration-files.mdx
💤 Files with no reviewable changes (1)
  • crates/cli/tests/coverage/server_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (33)
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/node/tests/plugin_tests.mjs
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/node/tests/plugin_tests.mjs
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/node/tests/plugin_tests.mjs
  • crates/ffi/src/api/plugin.rs
  • crates/ffi/nemo_relay.h
{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/node/tests/plugin_tests.mjs
  • crates/core/tests/unit/plugin_tests.rs
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
  • crates/core/src/plugin.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/core/tests/unit/plugin_tests.rs
**/{Cargo.toml,**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
  • crates/core/src/plugin.rs
**/*.{h,hpp,c,cpp,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
  • crates/ffi/nemo_relay.h
  • crates/core/src/plugin.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
  • crates/core/src/plugin.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
crates/{core,adaptive}/**

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
  • crates/core/src/plugin.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
  • crates/core/src/plugin.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/ffi/src/api/plugin.rs
  • crates/core/src/plugin.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/src/plugin.rs
{docs/**,README.md,CONTRIBUTING.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,examples/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

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.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/build-plugins/plugin-configuration-files.mdx
{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/build-plugins/plugin-configuration-files.mdx
crates/ffi/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

crates/ffi/src/api/**/*.rs: Add or update FFI wrappers in relevant crates/ffi/src/api/*.rs modules, re-export through crates/ffi/src/api/mod.rs, and ensure generated crates/ffi/nemo_relay.h stays correct
Use nemo_relay_ prefix for C FFI function names (e.g., nemo_relay_tool_call)

Files:

  • crates/ffi/src/api/plugin.rs
crates/ffi/**

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Rebuild the FFI crate in release mode so the shared library and header stay in sync when making changes to crates/ffi

Files:

  • crates/ffi/src/api/plugin.rs
  • crates/ffi/nemo_relay.h
crates/ffi/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/ffi, also use test-ffi-surface for validation

Files:

  • crates/ffi/src/api/plugin.rs
**/*.{h,c}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update C header names and symbol prefixes during coordinated rename operations

Files:

  • crates/ffi/nemo_relay.h
crates/ffi/nemo_relay.h

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Check the generated header diff when any exported symbol or type changed in the FFI surface

Ensure FFI header sync for crates/ffi/nemo_relay.h through Cargo/build.rs

Files:

  • crates/ffi/nemo_relay.h
crates/ffi/*.h

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Prefix C FFI exports with nemo_relay_

Files:

  • crates/ffi/nemo_relay.h
🔇 Additional comments (7)
docs/build-plugins/plugin-configuration-files.mdx (2)

188-188: Same binding-specific API naming issue at multiple locations.

The binding-specific API naming concern flagged in the past review for lines 85-88 also applies here. These lines use plugin.initialize(...) or initialize(...) as if it were a universal API, but Rust exposes initialize_plugins_from_discovered_config(...). Use binding-agnostic phrasing like "the binding-specific plugin initialization helper" at these locations as well.

Also applies to: 224-224, 315-315, 414-414


267-270: LGTM!

crates/core/src/plugin.rs (1)

15-16: LGTM!

Also applies to: 131-281, 307-495

crates/core/tests/unit/plugin_tests.rs (1)

589-647: LGTM!

Also applies to: 651-777

crates/ffi/nemo_relay.h (1)

1121-1170: LGTM!

crates/ffi/src/api/plugin.rs (1)

133-176: LGTM!

Also applies to: 178-212, 218-300

crates/node/tests/plugin_tests.mjs (1)

59-84: LGTM!

Comment thread crates/node/tests/plugin_tests.mjs
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
rapids-bot Bot pushed a commit that referenced this pull request Jun 2, 2026
…200)

#### Overview

Reorder the "Register Plugin Behavior" guide so a plugin kind is registered before it is activated, and document the `validate()`-warns / `initialize()`-raises behavior. Run on its own, the **Activation APIs** example previously failed with `RuntimeError: ... 'header-plugin' is not registered`, because the kind it activates is only registered later on the page in the **Header Plugin Example**.

- [x] I confirm this contribution is my own work, or I have the right to submit it under this project's license.
- [x] I searched existing issues and open pull requests, and this does not duplicate existing work.

#### Details

- `docs/build-plugins/register-behavior.mdx`: move the **Header Plugin Example** (which calls `plugin.register("header-plugin", ...)`) above the **Activation APIs** lifecycle so the page reads and runs top to bottom. Drop the now-redundant "Register the plugin kind" item from the activation list, and note that an unregistered kind is reported by `validate()` only as a warning under the default `unknown_component="warn"` policy, while `initialize()` raises. The reorder moves whole sections only; no code-block content changed (verified by an order-independent line diff).
- `docs/build-plugins/validate-configuration.mdx`: add the same clarification to **Validate Before Initialization** — the error-only `has_errors` check does not catch an unknown/unregistered kind; register kinds first, or set `unknown_component="error"`.

Heads-up: this edits the same `register-behavior.mdx` **Activation APIs** section as #199 (which adds `plugin.layer(...)` to that example but does not change the registration ordering). The two overlap, so whichever lands second will need a small conflict resolution.

#### Where should the reviewer start?

`docs/build-plugins/register-behavior.mdx` — confirm the section reorder preserved every code block (an order-independent line diff shows only the numbered list and intro changed) and that the Activation APIs example now follows the Header Plugin Example that registers the kind.

Verified locally: running the Header Plugin Example block and then the Activation APIs block in one process registers `header-plugin`, after which `validate()` / `initialize()` / `clear()` succeed with empty diagnostics and no `RuntimeError`. Targeted `pre-commit` (trailing whitespace, end-of-files, docs markdown linkcheck) passes on both files.

#### Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

- Relates to: #199 (edits the same `register-behavior.mdx` section)



## Summary by CodeRabbit

* **Documentation**
  * Clarified that plugin kinds must be registered before calling initialize()
  * Explained that unknown/unregistered component kinds are reported as warnings by default during validation and may still cause errors at initialization unless policy is changed
  * Reorganized and updated the activation guide and language across Python/Node/Rust examples for clearer ordering and guidance

Authors:
  - Zhongxuan (Daniel) Wang (https://github.com/zhongxuanwang-nv)

Approvers:
  - Will Killian (https://github.com/willkill07)

URL: #200
…r-code-driven-plugin-config

Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>

# Conflicts:
#	docs/build-plugins/register-behavior.mdx
Copy link
Copy Markdown

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/build-plugins/register-behavior.mdx`:
- Around line 196-200: Update the Rust example so it demonstrates the
recommended discovered-config layering: replace the call to
initialize_plugins(...) with
initialize_plugins_from_discovered_config(Some(...)) (or explicitly mark the
example as showing a non-layered/manual init) so the sample matches the prose
about layering; ensure the example uses
initialize_plugins_from_discovered_config and its Some(...) argument shape
consistent with other examples and mirrors the behavior described for
Python/Node (`plugin.initialize(...)`) to inherit/override file-backed config
fields.
🪄 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: a9323611-991c-4a70-ba5a-75fc7fdbbf8e

📥 Commits

Reviewing files that changed from the base of the PR and between 7ded734 and d47b5ec.

📒 Files selected for processing (2)
  • crates/node/src/api/mod.rs
  • docs/build-plugins/register-behavior.mdx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (23)
{docs/**,README.md,CONTRIBUTING.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/build-plugins/register-behavior.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/build-plugins/register-behavior.mdx
{docs/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/build-plugins/register-behavior.mdx
{docs/**,examples/**,README.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/build-plugins/register-behavior.mdx
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • docs/build-plugins/register-behavior.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current

Files:

  • docs/build-plugins/register-behavior.mdx
**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

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.

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

Files:

  • docs/build-plugins/register-behavior.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/build-plugins/register-behavior.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/build-plugins/register-behavior.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/build-plugins/register-behavior.mdx
{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/build-plugins/register-behavior.mdx
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/node/src/api/mod.rs
crates/node/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update Node.js binding in crates/node/src/api/mod.rs for language-native bindings

Files:

  • crates/node/src/api/mod.rs
crates/node/src/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Use camelCase naming convention for Node.js identifiers (e.g., toolCall)

Files:

  • crates/node/src/api/mod.rs
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/node/src/api/mod.rs
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/node/src/api/mod.rs
**/{Cargo.toml,**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/node/src/api/mod.rs
**/*.{h,hpp,c,cpp,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/node/src/api/mod.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/node/src/api/mod.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • crates/node/src/api/mod.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • crates/node/src/api/mod.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/node/src/api/mod.rs
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/node/src/api/mod.rs
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**} : Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
📚 Learning: 2026-05-21T22:48:28.092Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/contribute-integration/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:28.092Z
Learning: Applies to **/*.md : Documentation must be updated if activation or usage changed

Applied to files:

  • docs/build-plugins/register-behavior.mdx
📚 Learning: 2026-05-21T22:49:09.811Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**} : Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)

Applied to files:

  • docs/build-plugins/register-behavior.mdx
  • crates/node/src/api/mod.rs
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to crates/node/src/api/**/*.rs : Update Node.js binding in `crates/node/src/api/mod.rs` for language-native bindings

Applied to files:

  • crates/node/src/api/mod.rs
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to crates/wasm/src/api/**/*.rs : Update WebAssembly binding in `crates/wasm/src/api/mod.rs` for language-native bindings

Applied to files:

  • crates/node/src/api/mod.rs
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to crates/ffi/src/api/**/*.rs : Add or update FFI wrappers in relevant `crates/ffi/src/api/*.rs` modules, re-export through `crates/ffi/src/api/mod.rs`, and ensure generated `crates/ffi/nemo_relay.h` stays correct

Applied to files:

  • crates/node/src/api/mod.rs
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to {crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi} : Update Python native binding in `crates/python/src/py_api/mod.rs` with Python wrapper docstring in `python/nemo_relay/<module>.py` and type stubs in `python/nemo_relay/*.pyi` modules

Applied to files:

  • crates/node/src/api/mod.rs
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to crates/ffi/src/api/**/*.rs : Use `nemo_relay_` prefix for C FFI function names (e.g., `nemo_relay_tool_call`)

Applied to files:

  • crates/node/src/api/mod.rs
📚 Learning: 2026-05-29T21:25:49.977Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T21:25:49.977Z
Learning: Applies to crates/node/**/*.{js,ts,tsx} : Node.js public entry points include the main runtime package plus `nemo-relay-node/typed`, `nemo-relay-node/plugin`, and `nemo-relay-node/adaptive`.

Applied to files:

  • crates/node/src/api/mod.rs
🔇 Additional comments (1)
crates/node/src/api/mod.rs (1)

1338-1344: ⚡ Quick win

Clarify callback handle capture: no move-out/capture correctness issue with Arg0Builder
crates/node/src/promise_call.rs defines Arg0Builder as Box<dyn FnOnce(&Env) -> napi::Result<JsUnknown> + Send>, and crates/node/src/types/mod.rs implements From<CoreScopeHandle> for ScopeHandle. In crates/node/src/api/mod.rs::with_scope, callback_handle is captured by a move closure and passed to ScopeHandle::from(callback_handle); because the closure is FnOnce, consuming callback_handle inside the closure is safe, so the suggested callback_handle.clone() is unnecessary.

			> Likely an incorrect or invalid review comment.

Comment thread docs/build-plugins/register-behavior.mdx
@willkill07 willkill07 added this to the 0.4 milestone Jun 2, 2026
yczhang-nv pushed a commit to yczhang-nv/NeMo-Flow that referenced this pull request Jun 3, 2026
…VIDIA#200)

#### Overview

Reorder the "Register Plugin Behavior" guide so a plugin kind is registered before it is activated, and document the `validate()`-warns / `initialize()`-raises behavior. Run on its own, the **Activation APIs** example previously failed with `RuntimeError: ... 'header-plugin' is not registered`, because the kind it activates is only registered later on the page in the **Header Plugin Example**.

- [x] I confirm this contribution is my own work, or I have the right to submit it under this project's license.
- [x] I searched existing issues and open pull requests, and this does not duplicate existing work.

#### Details

- `docs/build-plugins/register-behavior.mdx`: move the **Header Plugin Example** (which calls `plugin.register("header-plugin", ...)`) above the **Activation APIs** lifecycle so the page reads and runs top to bottom. Drop the now-redundant "Register the plugin kind" item from the activation list, and note that an unregistered kind is reported by `validate()` only as a warning under the default `unknown_component="warn"` policy, while `initialize()` raises. The reorder moves whole sections only; no code-block content changed (verified by an order-independent line diff).
- `docs/build-plugins/validate-configuration.mdx`: add the same clarification to **Validate Before Initialization** — the error-only `has_errors` check does not catch an unknown/unregistered kind; register kinds first, or set `unknown_component="error"`.

Heads-up: this edits the same `register-behavior.mdx` **Activation APIs** section as NVIDIA#199 (which adds `plugin.layer(...)` to that example but does not change the registration ordering). The two overlap, so whichever lands second will need a small conflict resolution.

#### Where should the reviewer start?

`docs/build-plugins/register-behavior.mdx` — confirm the section reorder preserved every code block (an order-independent line diff shows only the numbered list and intro changed) and that the Activation APIs example now follows the Header Plugin Example that registers the kind.

Verified locally: running the Header Plugin Example block and then the Activation APIs block in one process registers `header-plugin`, after which `validate()` / `initialize()` / `clear()` succeed with empty diagnostics and no `RuntimeError`. Targeted `pre-commit` (trailing whitespace, end-of-files, docs markdown linkcheck) passes on both files.

#### Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

- Relates to: NVIDIA#199 (edits the same `register-behavior.mdx` section)

## Summary by CodeRabbit

* **Documentation**
  * Clarified that plugin kinds must be registered before calling initialize()
  * Explained that unknown/unregistered component kinds are reported as warnings by default during validation and may still cause errors at initialization unless policy is changed
  * Reorganized and updated the activation guide and language across Python/Node/Rust examples for clearer ordering and guidance

Authors:
  - Zhongxuan (Daniel) Wang (https://github.com/zhongxuanwang-nv)

Approvers:
  - Will Killian (https://github.com/willkill07)

URL: NVIDIA#200
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature a new feature lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:XL PR is extra large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants