feat(plugin): add native Rust plugin SDK#306
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a workspace plugin crate, a native Rust plugin SDK, typed callback tests, and a Rust cdylib example plugin with config, docs, and registration wiring. ChangesNative plugin support
Estimated code review effort🎯 5 (Critical) | ⏱️ ~90+ minutes Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
8048355 to
701970b
Compare
701970b to
8f90864
Compare
afourniernv
left a comment
There was a problem hiding this comment.
I think we should consider modularizing lib.rs / splitting it maybe at some point? Othewise LGTM.
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 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/plugin/src/lib.rs`:
- Around line 1797-1844: The typed_llm_request_intercept_trampoline callback is
publishing a partially written output pair when request serialization succeeds
but annotated serialization fails. Update this trampoline to preserve
all-or-nothing behavior by only assigning out_request_json and
out_annotated_json after both serializations succeed, or by cleaning up and
nulling the first output if the second write fails. Use
typed_llm_request_intercept_trampoline, write_json, and write_optional_json as
the key points to adjust the flow so no half-written host string is leaked on
error.
- Around line 2133-2141: The exported entrypoint generated by nemo_relay_plugin!
currently calls $constructor() through export_plugin without any panic boundary,
so a panic can abort the host. Update the macro’s extern "C" function to wrap
the full entry path in the same catch_unwind-based panic-to-status handling used
by the callback trampolines, and map any panic to NemoRelayStatus::Internal;
make sure this covers $constructor(), plugin_kind(), and
allows_multiple_components() through the existing export_plugin flow.
- Around line 2028-2041: The read_host_string helper is handling null and empty
inputs incorrectly: it currently maps a null value to an empty string and still
builds a slice from string_data() even when the pointer is null with zero
length. Update read_host_string in the plugin lib so a null handle returns None,
and add a len == 0 fast path before calling from_raw_parts; keep the existing
UTF-8 conversion for non-empty data and preserve the None result when
string_data() is null but len is positive.
In `@crates/plugin/tests/typed_callbacks.rs`:
- Around line 154-181: The fake host callbacks capture only the function
pointers and user data, so they do not verify that `PluginContext` is correctly
marshalling registration metadata. Update `capture_tool_request_intercept` and
`capture_tool_execution` to decode and store `name`, `priority`, and
`break_chain` in `RegisteredToolJson` and `RegisteredToolExecution`, then add
assertions in the corresponding registration tests to check those captured
values match what was passed through the API.
- Around line 595-646: The current test only verifies the success path for
ToolNext in typed_tool_execution_registration_calls_next and fake_tool_next, so
add coverage for failure handling too. Extend the typed execution trampoline
tests to simulate next.call returning a non-Ok NemoRelayStatus and to pass
malformed JSON through fake_tool_next, then assert the registration callback
surfaces the failure instead of swallowing it or mis-mapping the result. Keep
the new cases close to typed_tool_execution_registration_calls_next and reuse
ToolNext, fake_tool_next, and take_tool_execution_registration to locate the
behavior.
- Around line 63-74: The ABI test in typed_callbacks.rs only proves size
self-consistency because test_host().struct_size is derived from the same Rust
layout, so it can miss real C ABI breakage. Strengthen
native_abi_v1_struct_sizes_are_self_describing by asserting field offsets and
alignment for NemoRelayNativeHostApiV1 and NemoRelayNativePluginV1, or by
comparing the Rust layout against the generated C header/expected ABI layout, so
the test verifies actual layout compatibility rather than just matching
struct_size values.
- Around line 536-582: The error and panic paths in the typed callback test are
only checking status and LAST_ERROR, but they also need to verify that the
trampoline leaves out as null on failure. Update the assertions around the tool
registration callback in typed_callbacks.rs, using the existing registration.cb
invocation and out pointer setup, so both the callback failed and tool intercept
callback panicked paths confirm no output pointer is returned when
NemoRelayStatus::Internal is produced.
In `@examples/rust-native-plugin/relay-plugin.toml`:
- Around line 21-22: The checked-in relay manifest is macOS-specific because the
load.library value in relay-plugin.toml is hard-coded to a .dylib path with a
lib prefix. Update this manifest flow so it is portable across platforms by
using per-platform manifest variants or making the README explicitly instruct
users to edit the library path for Linux and Windows before activation, and keep
the relay-plugin.toml entry aligned with the actual platform-specific artifact
naming.
In `@examples/rust-native-plugin/src/lib.rs`:
- Around line 283-295: The `tag_json` helper is changing non-object `Json`
payloads into a new object shape in the `other` branch, which breaks valid
array/scalar `LlmRequest.content` values. Update `tag_json` so it only adds the
tag fields when the value is a `Json::Object`, and otherwise preserves the
original `Json` payload unchanged while still allowing the live tool/LLM
intercept callers to distinguish tagged objects via `tag_json`.
🪄 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: 0c04bd6c-7411-440a-a295-86cd829918f6
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
Cargo.tomlcrates/plugin/Cargo.tomlcrates/plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rsexamples/rust-native-plugin/.gitignoreexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rsjustfile
📜 Review details
⏰ Context from checks skipped due to timeout. (20)
- GitHub Check: WebAssembly / Test (windows-arm64)
- GitHub Check: Node.js / Test (macos-arm64)
- GitHub Check: WebAssembly / Test (windows-amd64)
- GitHub Check: WebAssembly / Test (linux-arm64)
- GitHub Check: Node.js / Test (windows-arm64)
- GitHub Check: Node.js / Test (windows-amd64)
- GitHub Check: WebAssembly / Test (linux-amd64)
- GitHub Check: Rust / Test (windows-amd64)
- GitHub Check: WebAssembly / Test (macos-arm64)
- GitHub Check: Python / Test (macos-arm64)
- GitHub Check: Rust / Test (windows-arm64)
- GitHub Check: Node.js / Test (linux-arm64)
- GitHub Check: Python / Test (windows-amd64)
- GitHub Check: Rust / Test (macos-arm64)
- GitHub Check: Rust / Test (linux-amd64)
- GitHub Check: Python / Test (windows-arm64)
- GitHub Check: Rust / Test (linux-arm64)
- GitHub Check: Go / Test (windows-arm64)
- GitHub Check: Go / Test (windows-amd64)
- GitHub Check: License Diff / Run
🧰 Additional context used
📓 Path-based instructions (26)
**/*.{rs,toml}
📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)
Update Rust crate names and module prefixes during coordinated rename operations
Files:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.toml
{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:
examples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rs
**/*.{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:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.md
**/*.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in TOML configuration files using hash comment syntax
Files:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/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:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points wasm/ # wasm-bindgen WebAssembly binding and JS wrappers python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile third_party/ # P...
Files:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.mdjustfileexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**/{Cargo.toml,**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Rust package names in
Cargo.tomland their actual usage across the codebase
Files:
Cargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**/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 asrelease/<major>.<minor>.
**/Cargo.toml: MaintainCargo.toml[workspace.package].versionas the source of truth for the Rust workspace and Python build versioning
KeepCargo.toml[workspace.dependencies]self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, runcargo check --workspaceto refreshCargo.lock
Files:
Cargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.toml
{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:
Cargo.tomlexamples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.md
**/*.{md,rst,html,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)
**/*.{md,rst,html,txt}: Always spellNVIDIAin all caps. Do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol afterNVIDIAwhen 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 withNVIDIAon 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 withs, not an apostrophe, such asGPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such asCPU,GPU,PC,API, andUIusually do not need to be spelled out for developer audiences.
Files:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.md
**/*.{md,rst,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
Spell
NVIDIAin all caps. Do not useNvidia,nvidia, orNV.
Files:
examples/rust-native-plugin/README.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.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce.
Preferrefer tooverseewhen 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:
examples/rust-native-plugin/README.md
{docs/**,README.md,CONTRIBUTING.md,**/*.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run docs link validation with
just docs-linkcheckwhen links change
Files:
examples/rust-native-plugin/README.md
**/*.{html,md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in HTML and Markdown files using HTML comment syntax
Files:
examples/rust-native-plugin/README.md
**/README.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update relevant crate or package README when that surface changed
Files:
examples/rust-native-plugin/README.md
justfile
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
justfile: Keep helper function inputs aligned when editing version helpers:set_project_versionshould call Cargo, Node, and coding-agent plugin version helpers for the same target version
Ensureset_cargo_workspace_versionhelper updates[workspace.package].versionplus all workspace.dependencies references (nemo-relay, nemo-relay-adaptive, nemo-relay-pii-redaction, nemo-relay-ffi, nemo-relay-cli)
Ensureset_node_package_versionshelper updates crates/node/package.json, integrations/openclaw/package.json, corresponding package-lock.json entries, and OpenClaw nemo-relay-node dependency entries
Files:
justfile
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}
⚙️ CodeRabbit configuration file
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}: Review automation changes for reproducibility, pinned versions where appropriate, secret handling, and consistency with the documented validation matrix.
Pay attention to commands that need generated native artifacts, FFI libraries, or platform-specific environment variables.
Files:
justfile
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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/plugin/tests/typed_callbacks.rs
🪛 LanguageTool
examples/rust-native-plugin/README.md
[style] ~72-~72: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...tion guardrails controlled by config. - Tool request and execution intercepts that m...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🔇 Additional comments (5)
crates/plugin/tests/typed_callbacks.rs (1)
1-1: 📐 Maintainability & Code QualityConfirm the required Rust validation commands.
This Rust change needs the repository-required Rust checks, but the PR objective only mentions package-scoped
cargo testpluscargo check -p nemo-relay-cli. Please confirmjust test-rust,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warningswere run.As per coding guidelines,
**/*.rs: “Any Rust change must runjust test-rust,” “Any Rust change must runcargo fmt --all,” and “Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings.”Source: Coding guidelines
crates/plugin/src/lib.rs (1)
1-5: 📐 Maintainability & Code QualityRun the full Rust validation matrix before merge. Include
cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warnings, andjust test-rustin the PR results.examples/rust-native-plugin/Cargo.toml (1)
1-19: LGTM!examples/rust-native-plugin/.gitignore (1)
1-5: LGTM!justfile (1)
847-848: LGTM!
8f90864 to
0dd53de
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 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/plugin/src/lib.rs`:
- Around line 1499-1508: The with_name helper is collapsing every
HostString::new failure into NemoRelayStatus::InvalidUtf8 even though the input
is already a Rust &str, so the real host allocation status is being lost. Update
with_name and the raw registration helpers that call it to propagate the actual
NemoRelayStatus returned by HostString::new/string_new instead of rewriting it,
while still passing the allocated pointer to the callback only on success.
- Around line 1950-2005: `PluginState<P>` is accessed mutably from both
`validate_trampoline` and `register_trampoline` through the shared `user_data`
ABI pointer without synchronization. Update the exported state handling in
`export_plugin` so the shared `PluginState<P>` is protected by a mutex, then
acquire that lock inside both trampolines before calling `validate` or
`register`. Map any lock poisoning or lock acquisition failure to
`NemoRelayStatus::Internal`, and keep the existing
`read_json_object`/`write_json` and `set_last_error` flow unchanged.
In `@crates/plugin/tests/typed_callbacks.rs`:
- Around line 64-69: The LLM intercept test helper currently ignores
registration metadata, so the test can miss bugs in
PluginContext::register_llm_request_intercept marshalling. Update
capture_llm_request_intercept and the
typed_llm_request_intercept_does_not_publish_partial_outputs test to mirror the
tool-registration assertions by recording and checking name, priority, and
break_chain alongside the callback fields. Ensure the captured registration
metadata is asserted where the intercept is registered so the test fails if any
of those fields are passed incorrectly.
In `@examples/rust-native-plugin/README.md`:
- Around line 39-41: The plugin activation example uses a
working-directory-dependent manifest path in the `nemo-relay plugins add`
command, which makes the snippet not copy/paste safe. Update the example around
`examples/rust-native-plugin/README.md` so the working directory is explicit or
both commands use the same path style, and keep the `nemo-relay plugins add` and
`nemo-relay plugins enable` flow consistent with the manifest reference used
later in the README.
- Around line 46-55: The TOML example under the rust-native-plugin README uses
an invalid multiline inline table for `plugins.dynamic.config`, so update the
example to use a valid TOML structure in the `[[plugins.dynamic]]` block by
switching to a nested `[plugins.dynamic.config]` table or keeping the inline
table on one line. Keep the `manifest` and `config` fields in the example
aligned with the `plugins.dynamic`/`config` symbols so the snippet can be copied
directly into `plugins.toml` without parse errors.
🪄 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: 397b8beb-6b10-4153-881d-08e90279efa0
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
Cargo.tomlcrates/plugin/Cargo.tomlcrates/plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rsexamples/rust-native-plugin/.gitignoreexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rsjustfile
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (26)
**/{Cargo.toml,**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Rust package names in
Cargo.tomland their actual usage across the codebase
Files:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**/*.{rs,toml}
📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)
Update Rust crate names and module prefixes during coordinated rename operations
Files:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/relay-plugin.toml
**/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 asrelease/<major>.<minor>.
**/Cargo.toml: MaintainCargo.toml[workspace.package].versionas the source of truth for the Rust workspace and Python build versioning
KeepCargo.toml[workspace.dependencies]self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, runcargo check --workspaceto refreshCargo.lock
Files:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.toml
{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:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.md
**/*.{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:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.toml
**/*.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in TOML configuration files using hash comment syntax
Files:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/relay-plugin.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:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points wasm/ # wasm-bindgen WebAssembly binding and JS wrappers python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile third_party/ # P...
Files:
Cargo.tomlcrates/plugin/Cargo.tomljustfileexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
justfile
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
justfile: Keep helper function inputs aligned when editing version helpers:set_project_versionshould call Cargo, Node, and coding-agent plugin version helpers for the same target version
Ensureset_cargo_workspace_versionhelper updates[workspace.package].versionplus all workspace.dependencies references (nemo-relay, nemo-relay-adaptive, nemo-relay-pii-redaction, nemo-relay-ffi, nemo-relay-cli)
Ensureset_node_package_versionshelper updates crates/node/package.json, integrations/openclaw/package.json, corresponding package-lock.json entries, and OpenClaw nemo-relay-node dependency entries
Files:
justfile
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}
⚙️ CodeRabbit configuration file
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}: Review automation changes for reproducibility, pinned versions where appropriate, secret handling, and consistency with the documented validation matrix.
Pay attention to commands that need generated native artifacts, FFI libraries, or platform-specific environment variables.
Files:
justfile
{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:
examples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rs
**/*.{md,rst,html,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)
**/*.{md,rst,html,txt}: Always spellNVIDIAin all caps. Do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol afterNVIDIAwhen 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 withNVIDIAon 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 withs, not an apostrophe, such asGPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such asCPU,GPU,PC,API, andUIusually do not need to be spelled out for developer audiences.
Files:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.md
**/*.{md,rst,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
Spell
NVIDIAin all caps. Do not useNvidia,nvidia, orNV.
Files:
examples/rust-native-plugin/README.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.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce.
Preferrefer tooverseewhen 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:
examples/rust-native-plugin/README.md
{docs/**,README.md,CONTRIBUTING.md,**/*.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run docs link validation with
just docs-linkcheckwhen links change
Files:
examples/rust-native-plugin/README.md
**/*.{html,md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in HTML and Markdown files using HTML comment syntax
Files:
examples/rust-native-plugin/README.md
**/README.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update relevant crate or package README when that surface changed
Files:
examples/rust-native-plugin/README.md
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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/plugin/tests/typed_callbacks.rs
🔇 Additional comments (1)
crates/plugin/Cargo.toml (1)
4-19: 📐 Maintainability & Code QualityPlease run the full Rust validation matrix for this new crate.
The PR notes targeted
cargo testandcargo checkruns, but repo policy for any Rust change requiresjust test-rust,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warningsbefore merge. As per coding guidelines,**/*.rs: "Any Rust change must runjust test-rust", "cargo fmt --all", and "cargo clippy --workspace --all-targets -- -D warnings."Source: Coding guidelines
0dd53de to
55d7c57
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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/plugin/src/lib.rs`:
- Around line 670-680: `ToolNext::call` and `LlmNext::call` should not assume a
non-null output pointer when `next_fn` returns `NemoRelayStatus::Ok`; add an
explicit null check on `out` before calling `read_json_value` or `string_free`.
If `out` is null, return a clear SDK error instead of continuing, and only free
the string after confirming it is valid so the FFI path cannot crash on a broken
continuation contract.
- Around line 1976-2000: Panic recovery in the native plugin trampolines is
returning NemoRelayStatus::Internal without updating the host error, so a
previous last_error can leak through. In validate_trampoline,
register_trampoline, and the exported entry path, handle the catch_unwind
failure by setting a fresh host error before returning Internal, using the same
error-reporting flow as callback_panic so the host always receives a new
diagnostic after a panic.
In `@crates/plugin/tests/typed_callbacks.rs`:
- Around line 1116-1129: The panic-entry tests only assert the returned Internal
status and reuse one plugin instance, so they miss cases where an entrypoint
partially mutates exported state before panicking. Update the typed callback
tests around constructor_panic_entry, plugin_kind_panic_entry, and
allows_multiple_panic_entry to use a fresh NemoRelayNativePluginV1::default()
for each call and explicitly verify that ownership-related fields such as
user_data, callbacks, and plugin_kind remain unset after the panic path.
- Around line 1016-1051: Add a typed test case for name-allocation failure in
register_tool_request_intercept, mirroring the raw-path coverage already
present. The new test should force String::new/name allocation to fail before
host registration, then assert the typed registration returns the allocation
error and that the captured callback state is dropped (e.g. via DropCounter), so
the boxed closure does not leak when user_data is never handed to the host.
In `@examples/rust-native-plugin/README.md`:
- Around line 63-73: The list under the “What the Example Registers” heading
starts immediately without a complete introductory sentence. Add a short lead-in
sentence before the bullet list in the README section so the list is introduced
by a full sentence, keeping the existing bullet items and wording intact.
In `@examples/rust-native-plugin/src/lib.rs`:
- Around line 145-153: The example is manually balancing scope lifecycle with
push_scope and pop_scope, which should be replaced with the SDK scope guard
helper. Update the native plugin flow around the runtime scope handling to use
the new guard-based API instead of explicitly calling push_scope/pop_scope, and
apply the same change in the other referenced scope block so the example
demonstrates the safer authoring-layer pattern using runtime and the
scope-related helper symbols consistently.
🪄 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: d64575ce-22bf-433c-8bbc-a7984869ce04
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
Cargo.tomlcrates/plugin/Cargo.tomlcrates/plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rsexamples/rust-native-plugin/.gitignoreexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rsjustfile
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (26)
**/{Cargo.toml,**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Rust package names in
Cargo.tomland their actual usage across the codebase
Files:
crates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.toml
**/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 asrelease/<major>.<minor>.
**/Cargo.toml: MaintainCargo.toml[workspace.package].versionas the source of truth for the Rust workspace and Python build versioning
KeepCargo.toml[workspace.dependencies]self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, runcargo check --workspaceto refreshCargo.lock
Files:
crates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/Cargo.toml
{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/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.md
**/*.{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/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.md
**/*.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in TOML configuration files using hash comment syntax
Files:
crates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/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/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points wasm/ # wasm-bindgen WebAssembly binding and JS wrappers python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile third_party/ # P...
Files:
crates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.tomljustfileexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
{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:
examples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rs
justfile
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
justfile: Keep helper function inputs aligned when editing version helpers:set_project_versionshould call Cargo, Node, and coding-agent plugin version helpers for the same target version
Ensureset_cargo_workspace_versionhelper updates[workspace.package].versionplus all workspace.dependencies references (nemo-relay, nemo-relay-adaptive, nemo-relay-pii-redaction, nemo-relay-ffi, nemo-relay-cli)
Ensureset_node_package_versionshelper updates crates/node/package.json, integrations/openclaw/package.json, corresponding package-lock.json entries, and OpenClaw nemo-relay-node dependency entries
Files:
justfile
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}
⚙️ CodeRabbit configuration file
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}: Review automation changes for reproducibility, pinned versions where appropriate, secret handling, and consistency with the documented validation matrix.
Pay attention to commands that need generated native artifacts, FFI libraries, or platform-specific environment variables.
Files:
justfile
**/*.{md,rst,html,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)
**/*.{md,rst,html,txt}: Always spellNVIDIAin all caps. Do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol afterNVIDIAwhen 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 withNVIDIAon 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 withs, not an apostrophe, such asGPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such asCPU,GPU,PC,API, andUIusually do not need to be spelled out for developer audiences.
Files:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.md
**/*.{md,rst,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
Spell
NVIDIAin all caps. Do not useNvidia,nvidia, orNV.
Files:
examples/rust-native-plugin/README.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.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce.
Preferrefer tooverseewhen 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:
examples/rust-native-plugin/README.md
{docs/**,README.md,CONTRIBUTING.md,**/*.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run docs link validation with
just docs-linkcheckwhen links change
Files:
examples/rust-native-plugin/README.md
**/*.{html,md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in HTML and Markdown files using HTML comment syntax
Files:
examples/rust-native-plugin/README.md
**/README.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update relevant crate or package README when that surface changed
Files:
examples/rust-native-plugin/README.md
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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/plugin/tests/typed_callbacks.rs
🔇 Additional comments (5)
crates/plugin/tests/typed_callbacks.rs (1)
1-1130: 📐 Maintainability & Code QualityConfirm the required Rust validation matrix ran.
The PR objectives list targeted
cargo testandcargo checkcommands, but this Rust change also needs confirmation forjust test-rust,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warnings.As per coding guidelines,
**/*.rs: “Any Rust change must runjust test-rust”, “Any Rust change must runcargo fmt --all”, and “Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings”.Source: Coding guidelines
Cargo.toml (1)
8-8: 📐 Maintainability & Code QualityConfirm the workspace-wide Cargo refresh.
Adding
crates/plugintomembersand[workspace.dependencies]changes the workspace graph, but the PR summary only shows package-scopedcargo test/cargo checkruns. Please confirmcargo check --workspacewas run so the new member/dependency wiring is validated against the full resolver state andCargo.lock. As per coding guidelines,After updating workspace package entries, run cargo check --workspace to refresh Cargo.lock.Also applies to: 30-30
Source: Coding guidelines
crates/plugin/Cargo.toml (1)
1-19: LGTM!crates/plugin/src/lib.rs (1)
1-17: 📐 Maintainability & Code QualityConfirm the required Rust validation matrix ran.
The PR summary lists targeted crate-level
cargo test/cargo checkcommands, but this new Rust surface should also have the repo-standardjust test-rust,cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings, anduv run pre-commit run --all-fileschecks before merge. As per coding guidelines,Any Rust change must run just test-rust,cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings, andValidate Rust code with uv run pre-commit run --all-files.Source: Coding guidelines
examples/rust-native-plugin/src/lib.rs (1)
1-294: 📐 Maintainability & Code QualityPlease include the full Rust validation matrix for this new crate.
The PR notes targeted package tests, but repo policy for any Rust change also expects
just test-rust,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warningsbefore merge. As per coding guidelines, any Rust change must runjust test-rust,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warnings.Source: Coding guidelines
55d7c57 to
9329e6a
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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/plugin/src/lib.rs`:
- Around line 1594-1906: The typed callback trampolines leave out-parameters
unchanged on early failure, which can leak stale values across the C ABI
boundary. Update the entry path in the relevant trampolines such as
typed_tool_sanitize_trampoline, typed_tool_intercept_trampoline,
typed_tool_conditional_trampoline, typed_tool_execution_trampoline,
typed_llm_sanitize_request_trampoline, typed_llm_sanitize_response_trampoline,
typed_llm_conditional_trampoline, typed_llm_request_intercept_trampoline, and
typed_llm_execution_trampoline to clear each out_* pointer immediately after the
null-pointer check and before any fallible read/callback work, so failures
always leave outputs null.
- Around line 1608-1609: The current `read_host_string` call sites are
collapsing both null ABI inputs and malformed UTF-8 into
`NemoRelayStatus::InvalidUtf8`, which misclassifies null pointers; update the
affected `plugin::lib` handlers to distinguish a null
`name`/`request_json`/`payload_json` from invalid encoding and return
`NemoRelayStatus::NullPointer` for null handles while keeping `InvalidUtf8` only
for malformed strings. Apply this in the relevant request-parsing paths that use
`read_host_string` before `read_json_value`, including the `name`/`payload_json`
and similar argument extraction sites listed in the review, so each ABI
violation surfaces the correct failure class.
In `@crates/plugin/tests/typed_callbacks.rs`:
- Around line 1075-1118: Add the missing failure-path coverage for LlmNext::call
in typed_callbacks.rs by mirroring the ToolNext::call tests for non-Ok relay
status and invalid JSON output, alongside the existing null-output case. Update
the typed_llm_execution_surfaces_null_next_output test area (and any nearby
LlmNext-focused helpers) to assert the same error mapping behavior, status
propagation, and LAST_ERROR handling as ToolNext so regressions in LLM
continuation paths are caught.
🪄 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: 6506f5ed-0300-4cc3-b295-b8ce2fe569ee
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
Cargo.tomlcrates/plugin/Cargo.tomlcrates/plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rsexamples/rust-native-plugin/.gitignoreexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rsjustfile
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (26)
justfile
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
justfile: Keep helper function inputs aligned when editing version helpers:set_project_versionshould call Cargo, Node, and coding-agent plugin version helpers for the same target version
Ensureset_cargo_workspace_versionhelper updates[workspace.package].versionplus all workspace.dependencies references (nemo-relay, nemo-relay-adaptive, nemo-relay-pii-redaction, nemo-relay-ffi, nemo-relay-cli)
Ensureset_node_package_versionshelper updates crates/node/package.json, integrations/openclaw/package.json, corresponding package-lock.json entries, and OpenClaw nemo-relay-node dependency entries
Files:
justfile
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points wasm/ # wasm-bindgen WebAssembly binding and JS wrappers python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile third_party/ # P...
Files:
justfileexamples/rust-native-plugin/relay-plugin.tomlCargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}
⚙️ CodeRabbit configuration file
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}: Review automation changes for reproducibility, pinned versions where appropriate, secret handling, and consistency with the documented validation matrix.
Pay attention to commands that need generated native artifacts, FFI libraries, or platform-specific environment variables.
Files:
justfile
**/*.{rs,toml}
📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)
Update Rust crate names and module prefixes during coordinated rename operations
Files:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.toml
{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:
examples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rs
**/*.{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:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.md
**/*.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in TOML configuration files using hash comment syntax
Files:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/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:
examples/rust-native-plugin/relay-plugin.tomlCargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**/{Cargo.toml,**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Rust package names in
Cargo.tomland their actual usage across the codebase
Files:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**/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 asrelease/<major>.<minor>.
**/Cargo.toml: MaintainCargo.toml[workspace.package].versionas the source of truth for the Rust workspace and Python build versioning
KeepCargo.toml[workspace.dependencies]self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, runcargo check --workspaceto refreshCargo.lock
Files:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.toml
{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:
Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.md
**/*.{md,rst,html,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)
**/*.{md,rst,html,txt}: Always spellNVIDIAin all caps. Do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol afterNVIDIAwhen 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 withNVIDIAon 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 withs, not an apostrophe, such asGPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such asCPU,GPU,PC,API, andUIusually do not need to be spelled out for developer audiences.
Files:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.md
**/*.{md,rst,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
Spell
NVIDIAin all caps. Do not useNvidia,nvidia, orNV.
Files:
examples/rust-native-plugin/README.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.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce.
Preferrefer tooverseewhen 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:
examples/rust-native-plugin/README.md
{docs/**,README.md,CONTRIBUTING.md,**/*.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run docs link validation with
just docs-linkcheckwhen links change
Files:
examples/rust-native-plugin/README.md
**/*.{html,md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in HTML and Markdown files using HTML comment syntax
Files:
examples/rust-native-plugin/README.md
**/README.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update relevant crate or package README when that surface changed
Files:
examples/rust-native-plugin/README.md
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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/plugin/tests/typed_callbacks.rs
🔇 Additional comments (6)
examples/rust-native-plugin/Cargo.toml (1)
1-19: LGTM!examples/rust-native-plugin/relay-plugin.toml (1)
1-24: LGTM!examples/rust-native-plugin/.gitignore (1)
1-5: LGTM!justfile (1)
817-848: LGTM!examples/rust-native-plugin/README.md (1)
1-78: LGTM!examples/rust-native-plugin/src/lib.rs (1)
1-295: 📐 Maintainability & Code QualityAdd the required Rust validation results before merge.
Include
just test-rust,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warningsfor this Rust change.
Signed-off-by: Will Killian <wkillian@nvidia.com>
9329e6a to
93e5b53
Compare
License DiffCompared against Lockfile license changesLockfile License ChangesRustAdded
Removed
Updated/Changed
NodeAdded
Removed
Updated/Changed
PythonAdded
Removed
Updated/Changed
Status output |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 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/plugin/src/lib.rs`:
- Around line 1829-1832: Wrap the C-ABI destructor paths in `catch_unwind` so
panics during user-owned `Drop` do not unwind across `extern "C"`. Update
`drop_typed_callback`, `drop_typed_llm_json_stream`, and `drop_plugin_state` in
the plugin runtime to catch any panic from `Box::from_raw`/drop and convert it
into `set_last_error(...)` instead of letting it escape. Keep the existing null
checks and ensure the error path records a useful message while the success path
still frees the boxed state normally.
- Around line 793-799: The raw LLM stream cleanup path in LlmStream::from_raw is
leaking host-owned user_data when validation fails on struct_size or a null next
callback. Update the from_raw construction flow in crates/plugin/src/lib.rs to
dispose of the incoming NemoRelayNativeLlmStreamV1 via its drop callback before
returning any error from those early checks, while preserving the existing
success path that wraps the raw stream after validation.
- Around line 2633-2648: Move the plugin constructor work behind the
`host`/`out` validation in `export_plugin()` so invalid pointers return before
any constructor side effects run. Also clear `*out` to
`NemoRelayNativePluginV1::default()` immediately after the null check and before
any ABI/version/allocation failures, so callers never see stale plugin data. Use
the existing `export_plugin`, `plugin.plugin_kind()`, and `HostString::new` flow
to keep the constructor-dependent setup after the early checks.
In `@crates/plugin/tests/typed_callbacks.rs`:
- Around line 1578-1580: The typed stream wrapper is only being verified on the
first chunk, so this test can miss later chunks bypassing the wrapper; update
the streamed chunk assertions in the typed callbacks test to also validate the
second chunk includes the expected wrapped shape using the existing
poll_stream_chunk flow and the chunk result, so the behavior promised by the
callback mapping is covered consistently across all emitted chunks.
- Around line 1623-1635: The failing-stream test only verifies that
NemoRelayNativeLlmStreamV1::next is unset, but the ABI contract also requires
the whole output struct to remain uninitialized on Internal. Tighten the
typed_callbacks.rs test around the registration.cb invocation by asserting that
NemoRelayNativeLlmStreamV1 fields such as user_data, cancel, and drop are also
still None after failing_llm_stream_next returns failure, so the regression is
covered for the full output state.
In `@examples/rust-native-plugin/src/lib.rs`:
- Line 72: The config field list is duplicated across ExampleConfig, parse, and
known_fields, which can drift and cause false unknown-field warnings. Update the
logic around known_fields in lib.rs so it is derived from a single source of
truth used by ExampleConfig and parse, rather than being maintained as a
hardcoded list. Keep the field names in one shared definition or generated from
the config representation, and ensure the warning check uses that shared set.
🪄 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: 10a7d433-e5aa-44a2-bb26-371e3e47379e
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (10)
Cargo.tomlcrates/plugin/Cargo.tomlcrates/plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rsexamples/rust-native-plugin/.gitignoreexamples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rsjustfile
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (26)
**/{Cargo.toml,**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Rust package names in
Cargo.tomland their actual usage across the codebase
Files:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**/*.{rs,toml}
📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)
Update Rust crate names and module prefixes during coordinated rename operations
Files:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.toml
**/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 asrelease/<major>.<minor>.
**/Cargo.toml: MaintainCargo.toml[workspace.package].versionas the source of truth for the Rust workspace and Python build versioning
KeepCargo.toml[workspace.dependencies]self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, runcargo check --workspaceto refreshCargo.lock
Files:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlCargo.toml
{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:
examples/rust-native-plugin/Cargo.tomlexamples/rust-native-plugin/README.mdexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.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:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.mdCargo.toml
**/*.{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:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.mdCargo.tomlexamples/rust-native-plugin/relay-plugin.toml
**/*.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in TOML configuration files using hash comment syntax
Files:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlCargo.tomlexamples/rust-native-plugin/relay-plugin.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:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.mdCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**
⚙️ CodeRabbit configuration file
**:AGENTS.md
This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.
Project Overview
NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.
The shared runtime model is:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.
Repository Structure
The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.crates/ core/ # Rust core runtime crate, published as nemo-relay adaptive/ # Adaptive runtime primitives and plugin components python/ # PyO3 native extension for the Python package ffi/ # Raw C ABI layer used by downstream bindings such as Go node/ # NAPI Node.js binding and JavaScript/TypeScript entry points wasm/ # wasm-bindgen WebAssembly binding and JS wrappers python/ nemo_relay/ # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers tests/ # Python tests go/ nemo_relay/ # Experimental Go CGo binding and tests fern/ # Fern documentation site scripts/ # Stable wrappers and helper scripts; build/test/docs entry points live in justfile third_party/ # P...
Files:
examples/rust-native-plugin/Cargo.tomlcrates/plugin/Cargo.tomlexamples/rust-native-plugin/README.mdjustfileCargo.tomlexamples/rust-native-plugin/relay-plugin.tomlexamples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.rs
**/*.{md,rst,html,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)
**/*.{md,rst,html,txt}: Always spellNVIDIAin all caps. Do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol afterNVIDIAwhen 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 withNVIDIAon 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 withs, not an apostrophe, such asGPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such asCPU,GPU,PC,API, andUIusually do not need to be spelled out for developer audiences.
Files:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.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:
examples/rust-native-plugin/README.md
**/*.{md,rst,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
Spell
NVIDIAin all caps. Do not useNvidia,nvidia, orNV.
Files:
examples/rust-native-plugin/README.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.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce.
Preferrefer tooverseewhen 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:
examples/rust-native-plugin/README.md
{docs/**,README.md,CONTRIBUTING.md,**/*.md}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
Run docs link validation with
just docs-linkcheckwhen links change
Files:
examples/rust-native-plugin/README.md
**/*.{html,md,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Include SPDX license header in HTML and Markdown files using HTML comment syntax
Files:
examples/rust-native-plugin/README.md
**/README.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Update relevant crate or package README when that surface changed
Files:
examples/rust-native-plugin/README.md
justfile
📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)
justfile: Keep helper function inputs aligned when editing version helpers:set_project_versionshould call Cargo, Node, and coding-agent plugin version helpers for the same target version
Ensureset_cargo_workspace_versionhelper updates[workspace.package].versionplus all workspace.dependencies references (nemo-relay, nemo-relay-adaptive, nemo-relay-pii-redaction, nemo-relay-ffi, nemo-relay-cli)
Ensureset_node_package_versionshelper updates crates/node/package.json, integrations/openclaw/package.json, corresponding package-lock.json entries, and OpenClaw nemo-relay-node dependency entries
Files:
justfile
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}
⚙️ CodeRabbit configuration file
{.github/**,.gitlab-ci.yml,.pre-commit-config.yaml,justfile,scripts/**}: Review automation changes for reproducibility, pinned versions where appropriate, secret handling, and consistency with the documented validation matrix.
Pay attention to commands that need generated native artifacts, FFI libraries, or platform-specific environment variables.
Files:
justfile
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
examples/rust-native-plugin/src/lib.rscrates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/plugin/tests/typed_callbacks.rscrates/plugin/src/lib.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/plugin/tests/typed_callbacks.rs
🔇 Additional comments (13)
examples/rust-native-plugin/src/lib.rs (5)
1-59: LGTM!
111-214: LGTM!
216-229: LGTM!
243-294: LGTM!
231-241: 🩺 Stability & AvailabilityNo deadlock path here. Native subscriber delivery is queued to a dispatcher thread, and event emission snapshots subscribers before releasing the runtime lock, so
emit_markcan be called from a subscriber without reentering a held non-reentrant lock.> Likely an incorrect or invalid review comment.Cargo.toml (1)
8-8: LGTM!Also applies to: 30-30
crates/plugin/Cargo.toml (1)
1-19: LGTM!examples/rust-native-plugin/Cargo.toml (1)
1-20: LGTM!examples/rust-native-plugin/.gitignore (1)
1-5: LGTM!examples/rust-native-plugin/README.md (1)
1-78: LGTM!justfile (1)
847-848: LGTM!examples/rust-native-plugin/relay-plugin.toml (1)
20-23: 🎯 Functional CorrectnessResolve
load.libraryrelative to the manifest directory (or make it absolute). The README adds./examples/rust-native-plugin/relay-plugin.tomlfrom the repo root, but the manifest keepstarget/debug/...as a relative path. If native loading uses that string as-is, the example only works from one working directory.crates/plugin/src/lib.rs (1)
1-2: 📐 Maintainability & Code QualityConfirm the required Rust validation commands before merge.
The PR validation list does not mention the repo-required full Rust checks. Please confirm
just test-rust,cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warningswere run for this Rust SDK change. As per coding guidelines, “Any Rust change must runjust test-rust”, “Any Rust change must runcargo fmt --all”, and “Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings”.Source: Coding guidelines
| let mut raw = NemoRelayNativeLlmStreamV1::default(); | ||
| let status = unsafe { (self.next_fn)(request.as_ptr(), self.next_ctx, &mut raw) }; | ||
| if status != NemoRelayStatus::Ok { | ||
| return Err(format!("llm stream next failed: {status:?}")); | ||
| } | ||
| unsafe { LlmStream::from_raw(self.host, raw) } | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
set -euo pipefail
git ls-files crates/plugin/src/lib.rs crates/plugin/src
wc -l crates/plugin/src/lib.rs
rg -n "from_raw|drop_raw_llm_stream|LlmStreamNext::call|NemoRelayNativeLlmStreamV1" crates/plugin/src/lib.rs
sed -n '760,860p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 5291
🏁 Script executed:
set -euo pipefail
git ls-files crates/plugin/src/lib.rs crates/plugin/src
wc -l crates/plugin/src/lib.rs
rg -n "from_raw|drop_raw_llm_stream|LlmStreamNext::call|NemoRelayNativeLlmStreamV1" crates/plugin/src/lib.rs
sed -n '760,860p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 5291
🏁 Script executed:
set -euo pipefail
sed -n '140,240p' crates/plugin/src/lib.rs
sed -n '2200,2365p' crates/plugin/src/lib.rs
sed -n '2365,2465p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 12791
🏁 Script executed:
sed -n '140,240p' crates/plugin/src/lib.rs
sed -n '2200,2365p' crates/plugin/src/lib.rs
sed -n '2365,2465p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 12791
🏁 Script executed:
set -euo pipefail
rg -n "impl Drop for LlmStream|drop_fn|user_data|struct NemoRelayNativeLlmStreamV1|type .*LlmStreamNextFn|NemoRelayNativeLlmStreamNextFn" crates/plugin/src/lib.rs
sed -n '150,210p' crates/plugin/src/lib.rs
sed -n '2228,2345p' crates/plugin/src/lib.rs
sed -n '810,910p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 20963
🏁 Script executed:
set -euo pipefail
rg -n "impl Drop for LlmStream|drop_fn|user_data|struct NemoRelayNativeLlmStreamV1|type .*LlmStreamNextFn|NemoRelayNativeLlmStreamNextFn" crates/plugin/src/lib.rs
sed -n '150,210p' crates/plugin/src/lib.rs
sed -n '2228,2345p' crates/plugin/src/lib.rs
sed -n '810,910p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 20963
Free rejected raw LLM streams. In crates/plugin/src/lib.rs:818-830, LlmStream::from_raw returns early on invalid struct_size or a null next callback without invoking the raw stream’s drop callback, so a host-owned user_data can leak. Clean up the raw table before returning the error.
🤖 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/plugin/src/lib.rs` around lines 793 - 799, The raw LLM stream cleanup
path in LlmStream::from_raw is leaking host-owned user_data when validation
fails on struct_size or a null next callback. Update the from_raw construction
flow in crates/plugin/src/lib.rs to dispose of the incoming
NemoRelayNativeLlmStreamV1 via its drop callback before returning any error from
those early checks, while preserving the existing success path that wraps the
raw stream after validation.
| unsafe extern "C" fn drop_typed_callback<F>(user_data: *mut c_void) { | ||
| if !user_data.is_null() { | ||
| drop(unsafe { Box::from_raw(user_data as *mut TypedCallback<F>) }); | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical
🧩 Analysis chain
🏁 Script executed:
# Inspect the relevant Rust file and all extern "C" destructors around the cited ranges.
sed -n '1780,1865p' crates/plugin/src/lib.rs
printf '\n----\n'
sed -n '2280,2335p' crates/plugin/src/lib.rs
printf '\n----\n'
sed -n '2390,2455p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 6935
🏁 Script executed:
# Find all extern "C" drop/cleanup functions in the plugin crate.
rg -n 'unsafe extern "C" fn drop_|extern "C" fn drop_|catch_unwind|set_last_error' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 3148
🏁 Script executed:
# Check whether any other extern "C" drop/destructor-style functions exist in this crate.
rg -n 'unsafe extern "C" fn .*drop|unsafe extern "C" fn .*free|unsafe extern "C" fn .*destroy' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 396
Wrap the C-ABI destructors in catch_unwind.
drop_typed_callback, drop_typed_llm_json_stream, and drop_plugin_state can unwind through extern "C" if user-owned state panics during Drop, which can abort the host. Convert that to set_last_error(...) instead of letting the unwind escape.
🤖 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/plugin/src/lib.rs` around lines 1829 - 1832, Wrap the C-ABI destructor
paths in `catch_unwind` so panics during user-owned `Drop` do not unwind across
`extern "C"`. Update `drop_typed_callback`, `drop_typed_llm_json_stream`, and
`drop_plugin_state` in the plugin runtime to catch any panic from
`Box::from_raw`/drop and convert it into `set_last_error(...)` instead of
letting it escape. Keep the existing null checks and ensure the error path
records a useful message while the success path still frees the boxed state
normally.
| if host.is_null() || out.is_null() { | ||
| return NemoRelayStatus::NullPointer; | ||
| } | ||
| let host_ref = unsafe { &*host }; | ||
| if host_ref.abi_version != NEMO_RELAY_NATIVE_ABI_VERSION { | ||
| return NemoRelayStatus::InvalidArg; | ||
| } | ||
| if host_ref.struct_size < std::mem::size_of::<NemoRelayNativeHostApiV1>() { | ||
| return NemoRelayStatus::InvalidArg; | ||
| } | ||
|
|
||
| let kind = plugin.plugin_kind().to_owned(); | ||
| let allows_multiple_components = plugin.allows_multiple_components(); | ||
| let Some(kind_handle) = HostString::new(host_ref, &kind) else { | ||
| return NemoRelayStatus::Internal; | ||
| }; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the relevant functions/macros in crates/plugin/src/lib.rs
ast-grep outline crates/plugin/src/lib.rs --view expanded || true
printf '\n--- search export_plugin / macro sites ---\n'
rg -n "export_plugin|catch_unwind|NemoRelayNativePluginV1::default|NullPointer|InvalidArg" crates/plugin/src/lib.rs
printf '\n--- focused slice around the reported lines ---\n'
sed -n '2610,2705p' crates/plugin/src/lib.rsRepository: NVIDIA/NeMo-Relay
Length of output: 18934
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Provide line numbers and surrounding context for the relevant block.
nl -ba crates/plugin/src/lib.rs | sed -n '2618,2705p'Repository: NVIDIA/NeMo-Relay
Length of output: 195
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the exported helper and the macro expansion target.
nl -ba crates/plugin/src/lib.rs | sed -n '2580,2665p'
printf '\n---\n'
nl -ba crates/plugin/src/lib.rs | sed -n '2665,2715p'Repository: NVIDIA/NeMo-Relay
Length of output: 195
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Minimal verification: inspect the functions surrounding the reported lines.
nl -ba crates/plugin/src/lib.rs | sed -n '2620,2705p'Repository: NVIDIA/NeMo-Relay
Length of output: 195
Move the constructor behind the argument checks, and clear the output on failure.
- The generated entry wrapper evaluates
$constructor()beforeexport_plugin(), so invalidhost/outpointers still trigger constructor side effects. export_plugin()should initialize*outtoNemoRelayNativePluginV1::default()after the null check, before ABI/version/allocation failure paths, so callers don’t observe stale descriptor contents.
🤖 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/plugin/src/lib.rs` around lines 2633 - 2648, Move the plugin
constructor work behind the `host`/`out` validation in `export_plugin()` so
invalid pointers return before any constructor side effects run. Also clear
`*out` to `NemoRelayNativePluginV1::default()` immediately after the null check
and before any ABI/version/allocation failures, so callers never see stale
plugin data. Use the existing `export_plugin`, `plugin.plugin_kind()`, and
`HostString::new` flow to keep the constructor-dependent setup after the early
checks.
| let (status, chunk) = poll_stream_chunk(&host, &stream); | ||
| assert_eq!(status, NemoRelayStatus::Ok); | ||
| assert_eq!(chunk.unwrap()["chunk"], json!(2)); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert wrapping on every streamed chunk.
The callback maps all chunks, but the test only verifies "wrapped" on the first chunk. Check it on the second chunk too so later chunks cannot silently bypass the typed stream wrapper.
As per path instructions, tests in crates/**/tests/** should cover the behavior promised by the changed API surface.
Suggested assertion
let (status, chunk) = poll_stream_chunk(&host, &stream);
assert_eq!(status, NemoRelayStatus::Ok);
- assert_eq!(chunk.unwrap()["chunk"], json!(2));
+ let chunk = chunk.unwrap();
+ assert_eq!(chunk["chunk"], json!(2));
+ assert_eq!(chunk["wrapped"], json!(true));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let (status, chunk) = poll_stream_chunk(&host, &stream); | |
| assert_eq!(status, NemoRelayStatus::Ok); | |
| assert_eq!(chunk.unwrap()["chunk"], json!(2)); | |
| let (status, chunk) = poll_stream_chunk(&host, &stream); | |
| assert_eq!(status, NemoRelayStatus::Ok); | |
| let chunk = chunk.unwrap(); | |
| assert_eq!(chunk["chunk"], json!(2)); | |
| assert_eq!(chunk["wrapped"], json!(true)); |
🤖 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/plugin/tests/typed_callbacks.rs` around lines 1578 - 1580, The typed
stream wrapper is only being verified on the first chunk, so this test can miss
later chunks bypassing the wrapper; update the streamed chunk assertions in the
typed callbacks test to also validate the second chunk includes the expected
wrapped shape using the existing poll_stream_chunk flow and the chunk result, so
the behavior promised by the callback mapping is covered consistently across all
emitted chunks.
Source: Path instructions
| let mut stream = NemoRelayNativeLlmStreamV1::default(); | ||
| let status = unsafe { | ||
| (registration.cb)( | ||
| registration.user_data as *mut c_void, | ||
| name, | ||
| request, | ||
| failing_llm_stream_next, | ||
| next_state.cast(), | ||
| &mut stream, | ||
| ) | ||
| }; | ||
| assert_eq!(status, NemoRelayStatus::Internal); | ||
| assert!(stream.next.is_none()); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Assert the failed stream output stays fully uninitialized.
Line 1635 only checks next; a regression could still leave user_data, cancel, or drop set after returning Internal, creating an ambiguous ABI ownership handoff.
As per path instructions, tests in crates/**/tests/** should cover the behavior promised by the changed API surface, including error paths.
Suggested test tightening
assert_eq!(status, NemoRelayStatus::Internal);
+ assert_eq!(
+ stream.struct_size,
+ NemoRelayNativeLlmStreamV1::default().struct_size
+ );
+ assert!(stream.user_data.is_null());
assert!(stream.next.is_none());
+ assert!(stream.cancel.is_none());
+ assert!(stream.drop.is_none());
assert_eq!(called.load(Ordering::SeqCst), 1);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let mut stream = NemoRelayNativeLlmStreamV1::default(); | |
| let status = unsafe { | |
| (registration.cb)( | |
| registration.user_data as *mut c_void, | |
| name, | |
| request, | |
| failing_llm_stream_next, | |
| next_state.cast(), | |
| &mut stream, | |
| ) | |
| }; | |
| assert_eq!(status, NemoRelayStatus::Internal); | |
| assert!(stream.next.is_none()); | |
| let mut stream = NemoRelayNativeLlmStreamV1::default(); | |
| let status = unsafe { | |
| (registration.cb)( | |
| registration.user_data as *mut c_void, | |
| name, | |
| request, | |
| failing_llm_stream_next, | |
| next_state.cast(), | |
| &mut stream, | |
| ) | |
| }; | |
| assert_eq!(status, NemoRelayStatus::Internal); | |
| assert_eq!( | |
| stream.struct_size, | |
| NemoRelayNativeLlmStreamV1::default().struct_size | |
| ); | |
| assert!(stream.user_data.is_null()); | |
| assert!(stream.next.is_none()); | |
| assert!(stream.cancel.is_none()); | |
| assert!(stream.drop.is_none()); |
🤖 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/plugin/tests/typed_callbacks.rs` around lines 1623 - 1635, The
failing-stream test only verifies that NemoRelayNativeLlmStreamV1::next is
unset, but the ABI contract also requires the whole output struct to remain
uninitialized on Internal. Tighten the typed_callbacks.rs test around the
registration.cb invocation by asserting that NemoRelayNativeLlmStreamV1 fields
such as user_data, cancel, and drop are also still None after
failing_llm_stream_next returns failure, so the regression is covered for the
full output state.
Source: Path instructions
|
|
||
| fn validate(&self, plugin_config: &Map<String, Json>) -> Vec<ConfigDiagnostic> { | ||
| let mut diagnostics = Vec::new(); | ||
| let known_fields = ["tag", "block_tools", "block_llms", "emit_isolated_scope"]; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
Field knowledge is triplicated.
The config field names live in three places: the ExampleConfig struct (lines 13-17), parse (lines 35-55), and known_fields here. Adding a field means updating all three, and forgetting known_fields would emit a spurious "unknown config field" warning for a field the plugin actually consumes. Consider deriving known_fields from a single source.
🤖 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 `@examples/rust-native-plugin/src/lib.rs` at line 72, The config field list is
duplicated across ExampleConfig, parse, and known_fields, which can drift and
cause false unknown-field warnings. Update the logic around known_fields in
lib.rs so it is derived from a single source of truth used by ExampleConfig and
parse, rather than being maintained as a hardcoded list. Keep the field names in
one shared definition or generated from the config representation, and ensure
the warning check uses that shared set.
Overview
Add the Rust native plugin authoring SDK on top of the shared DTO crate.
Stack dependency: this PR cannot be merged until parent stacked PR #305 is merged: #305
Details
nemo-relay-pluginwith the stable native C ABI v1.Validation run across the completed stack:
cargo test -p nemo-relay-typescargo test -p nemo-relay-plugincargo test -p nemo-relay-worker-protocargo test -p nemo-relay-workercargo check -p nemo-relay-cliWhere should the reviewer start?
Start with
crates/plugin/src/lib.rs, then checkcrates/plugin/tests/typed_callbacks.rs.Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit
New Features
Tests
Documentation
Chores