Skip to content

feat(plugin): load rust_dynamic plugins in relay#307

Merged
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
willkill07:wkk_dynamic-plugin-3-native-loader
Jun 26, 2026
Merged

feat(plugin): load rust_dynamic plugins in relay#307
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
willkill07:wkk_dynamic-plugin-3-native-loader

Conversation

@willkill07

@willkill07 willkill07 commented Jun 25, 2026

Copy link
Copy Markdown
Member

Overview

Add the host-side rust_dynamic native plugin loader and gateway activation path.

Stack dependency: this PR cannot be merged until parent stacked PR #306 is merged: #306

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

Details

  • Load trusted in-process native dynamic plugins through the stable ABI.
  • Register native plugin kinds into the existing plugin registry and clear them before library unload.
  • Add native plugin gateway activation, fixture coverage, and integration tests.

Validation run across the completed stack:

  • cargo test -p nemo-relay-types
  • cargo test -p nemo-relay-plugin
  • cargo test -p nemo-relay-worker-proto
  • cargo test -p nemo-relay-worker
  • cargo check -p nemo-relay-cli

Where should the reviewer start?

Start with crates/core/src/plugin/dynamic/native.rs, then review the activation wiring in crates/cli/src/server.rs.

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

Summary by CodeRabbit

  • New Features
    • Transparent runs now automatically activate dynamic plugins (including daemon-mode startup).
    • Added end-to-end support for native dynamic plugins from manifests, including loading validation and runtime activation.
  • Bug Fixes
    • Improved dynamic-plugin lifecycle handling so activation is correctly initialized/cleared, including proper failure/rollback behavior.
    • Dry-run no longer hydrates dynamic plugin lifecycle state.
  • Tests
    • Expanded coverage for active dynamic plugin resolution and native plugin integration, including negative/error scenarios and lifecycle transitions.
  • Refactor
    • Gateway startup was updated to use a dynamic-plugin-aware serving path.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds native dynamic plugin loading, computes active dynamic plugin components from CLI lifecycle state, threads them through daemon and transparent run startup, adds a scope-stack override for synchronous native callbacks, and expands fixture and integration test coverage.

Changes

Native dynamic plugins

Layer / File(s) Summary
Scope stack override
crates/core/src/api/runtime.rs, crates/core/src/api/runtime/scope_stack.rs
Adds a thread-local scope-stack override, with_scope_stack, and override-aware scope-stack lookup.
Native loader
crates/core/Cargo.toml, crates/core/src/plugin/dynamic.rs, crates/core/src/plugin/dynamic/native.rs
Adds native plugin load specs, activation state, manifest and compatibility checks, host ABI bridging, callback plumbing, and non-wasm gating for dynamic plugins.
CLI dynamic resolution
crates/cli/src/config.rs, crates/cli/src/plugins/lifecycle.rs, crates/cli/src/main.rs, crates/cli/tests/coverage/main_tests.rs, crates/cli/tests/coverage/plugins_lifecycle_tests.rs
Hydrates active dynamic plugin components from lifecycle state, skips required-startup enforcement in dry runs, and uses the derived components in daemon-mode startup and lifecycle coverage.
CLI gateway startup
crates/cli/src/launcher.rs, crates/cli/src/server.rs, crates/cli/tests/coverage/server_tests.rs, crates/cli/tests/coverage/launcher_tests.rs
Threads active dynamic plugin components through transparent runs and server startup, initializes plugin activation with native plugin loading, and adds startup and dry-run coverage.
Native fixture and tests
crates/core/Cargo.toml, crates/core/tests/fixtures/native_plugin/*, crates/core/tests/integration/native_plugin_tests.rs
Adds the native plugin fixture crate and integration tests for loading, rollback, validation, and interception.

Sequence Diagram(s)

sequenceDiagram
  participant run_default
  participant active_dynamic_plugin_components
  participant serve_with_dynamic
  participant serve_listener_with_dynamic
  participant PluginActivation_initialize as "PluginActivation::initialize"
  participant load_native_plugins

  run_default->>active_dynamic_plugin_components: compute dynamic_plugins from resolved config
  run_default->>serve_with_dynamic: start gateway with dynamic_plugins
  serve_with_dynamic->>serve_listener_with_dynamic: bind listener and serve
  serve_listener_with_dynamic->>PluginActivation_initialize: initialize(config.plugin_config, dynamic_plugins)
  PluginActivation_initialize->>load_native_plugins: load RustDynamic specs
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

Possibly related PRs

  • NVIDIA/NeMo-Relay#279: Introduces the dynamic plugin types and lifecycle semantics consumed by the CLI and server wiring in this PR.
  • NVIDIA/NeMo-Relay#290: Populates ResolvedConfig.dynamic_plugins, which this PR reads when computing active dynamic plugin components.
  • NVIDIA/NeMo-Relay#292: Adds CLI lifecycle state and dynamic plugin persistence that active_dynamic_plugin_components hydrates during startup.

Suggested labels

DO NOT MERGE

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.40% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows Conventional Commits and accurately summarizes the main change.
Description check ✅ Passed The description includes the required overview, details, reviewer start, checklist items, and related issues.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the size:XXL PR is very large label Jun 25, 2026
@github-actions github-actions Bot added Feature a new feature lang:rust PR changes/introduces Rust code labels Jun 25, 2026
@github-actions

Copy link
Copy Markdown

@willkill07 willkill07 self-assigned this Jun 25, 2026
@willkill07 willkill07 added this to the 0.5 milestone Jun 25, 2026
@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 95aee26 to a2eb759 Compare June 25, 2026 18:16
@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from a2eb759 to 096d576 Compare June 25, 2026 18:44
@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 096d576 to 186668d Compare June 25, 2026 23:21
@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 186668d to 0c89f8f Compare June 25, 2026 23:40
@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 0c89f8f to 0171643 Compare June 26, 2026 00:19
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 0171643 to e118a8b Compare June 26, 2026 00:45
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from e118a8b to 54be92c Compare June 26, 2026 02:28
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 54be92c to d5f5b7c Compare June 26, 2026 12:07
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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/cli/src/launcher.rs`:
- Around line 104-112: The `run` launcher path is hydrating lifecycle state too
early: `active_dynamic_plugin_components()` calls into
`load_and_hydrate_scopes()`, so `--dry-run` can still rewrite state before the
early return. Update the `run` flow in `launcher.rs` to skip dynamic plugin
resolution when `resolved` indicates a dry run, or split
`active_dynamic_plugin_components()` into a read-only path and use that here so
`dry-run` remains side-effect free.

In `@crates/cli/src/plugins/lifecycle.rs`:
- Around line 377-381: The plugin activation path is requiring a manifest
reference too early in the lifecycle flow. In lifecycle.rs, update the
ActiveDynamicPluginComponent construction so `manifest_ref` is only fetched for
native/Rust dynamic plugins (for example by checking
`DynamicPluginKind::RustDynamic` before calling `manifest_ref_from_record`), or
make the field optional and resolve it later where it is actually consumed. This
should be handled in the `components.push(ActiveDynamicPluginComponent { ... })`
block so enabled worker records without `source.manifest_ref` do not fail
startup.

In `@crates/core/Cargo.toml`:
- Around line 78-86: The native plugin dependencies are still declared in the
general dependencies section even though only dynamic::native uses them on
non-wasm targets. Move nemo-relay-plugin, libloading, semver, and sha2 into the
target.'cfg(not(target_arch = "wasm32"))'.dependencies section in Cargo.toml,
keeping the wasm-safe dependencies separate so wasm builds do not resolve
native-only crates.

In `@crates/core/src/plugin/dynamic/native.rs`:
- Around line 88-93: The dynamic plugin activation currently unloads the Library
in NativePluginActivation::Drop while registered callbacks still rely on
NativeCallbackUserData pointers, which can leave middleware holding dangling
references. Update the callback registration path in native.rs to thread an
Arc<NativePluginInstance> into the registered callback state so the library
stays alive for as long as those closures exist. Make the lifecycle ownership
flow through the callback setup and deregistration code, including the related
callback registration logic near the referenced block, so dropping
NativePluginActivation does not invalidate active callback/free_fn pointers.

In `@crates/core/tests/integration/native_plugin_tests.rs`:
- Around line 1-23: Gate the native plugin integration test module on non-wasm
targets because it depends on `std::process::Command` and `load_native_plugins`
to load native dynamic plugins, which should not run under wasm32. Add the
appropriate target restriction around the `native_plugin_tests.rs` test setup or
module so the tests are compiled and executed only for native targets, using the
existing `load_native_plugins` and `Command`-based flow as the location to apply
the guard.
🪄 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: 80be1e1d-dc5e-454b-b9f3-d6b929589882

📥 Commits

Reviewing files that changed from the base of the PR and between b737b7a and 385f7ed.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • crates/cli/src/launcher.rs
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/src/server.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (20)
**/{Cargo.toml,**/*.rs}

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

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{py,txt,toml,cfg,yaml,yml}

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

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/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 as release/<major>.<minor>.

**/Cargo.toml: Maintain Cargo.toml [workspace.package].version as the source of truth for the Rust workspace and Python build versioning
Keep Cargo.toml [workspace.dependencies] self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, run cargo check --workspace to refresh Cargo.lock

Files:

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

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

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/plugin/dynamic/native.rs
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

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

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/Cargo.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:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/Cargo.toml
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

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

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.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:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. 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/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.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/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
**/*.rs

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

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

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

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

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

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

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

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

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

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

Files:

  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{h,hpp,c,cpp,rs}

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

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

Files:

  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/cli/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/api/runtime.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/src/launcher.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/core/**/*.rs

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

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

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

Files:

  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/core/src/api/**/*.rs

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

Implement behavior first in Rust core API modules: crates/core/src/api/ and related core modules such as crates/core/src/api/runtime/, crates/core/src/codec/, or crates/core/src/json.rs

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
🔇 Additional comments (10)
crates/core/src/api/runtime.rs (1)

23-23: LGTM!

crates/core/src/api/runtime/scope_stack.rs (2)

260-262: LGTM!

Also applies to: 385-388


289-308: 🩺 Stability & Availability

No action needed here: native_scope_stack_with_current is a synchronous trampoline, and the block_on paths live in separate *_next helpers on dedicated threads.

			> Likely an incorrect or invalid review comment.
crates/cli/tests/coverage/plugins_lifecycle_tests.rs (1)

419-423: Still missing the native kind assertion here.

crates/cli/src/server.rs (1)

246-290: Native activation cleanup still looks incomplete on the failure/teardown paths.

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

1499-1501: Unresolved duplicate: restore the active scope stack inside helper threads.

These std::thread::spawn(... block_on(next(...))) paths still drop the caller’s thread-local scope stack before downstream execution/stream polling runs.

Also applies to: 1760-1762, 1839-1840, 2018-2039

crates/core/Cargo.toml (1)

123-126: LGTM!

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

22-28: LGTM!

crates/core/tests/fixtures/native_plugin/Cargo.toml (1)

1-18: LGTM!

crates/core/tests/fixtures/native_plugin/src/lib.rs (1)

1-445: LGTM!

Comment thread crates/cli/src/launcher.rs Outdated
Comment thread crates/cli/src/plugins/lifecycle.rs
Comment thread crates/core/Cargo.toml Outdated
Comment thread crates/core/src/plugin/dynamic/native.rs
Comment thread crates/core/tests/integration/native_plugin_tests.rs
@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 385f7ed to ca21ca9 Compare June 26, 2026 15:47
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/cli/tests/coverage/server_tests.rs`:
- Around line 179-203: The fixture in the server coverage test is hard-coded to
a relay compatibility range, which can make the test fail on version bumps
before it reaches the missing-library path. Update the manifest generation in
the test around the `plugin_id`/`library` fixture so the `[compat] relay` value
is derived from the current crate version via `env!("CARGO_PKG_VERSION")`
instead of the fixed `">=0.5,<1.0"` range. This keeps the `server_tests` fixture
aligned with the workspace version source of truth while preserving the intended
missing-native-plugin assertion.

In `@crates/core/tests/integration/native_plugin_tests.rs`:
- Around line 57-81: The test leaves process-global state registered until the
end of the function, so a panic can bypass cleanup and leave the
subscriber/plugin config active while activation unwinds. Add an RAII cleanup
guard in the native plugin test setup, declared after
load_native_plugins/activation, that unregisters native_plugin_fixture_events
and clears the plugin configuration before activation drops, ensuring cleanup
runs on both normal and panic paths. Use the existing initialize_plugins_exact,
register_subscriber, and activation handles to place the guard correctly.
🪄 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: 91f4ccca-858a-4a85-a228-9c5b4e1aee9e

📥 Commits

Reviewing files that changed from the base of the PR and between 385f7ed and ca21ca9.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • crates/cli/src/launcher.rs
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/src/server.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (20)
crates/core/src/api/**/*.rs

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

Implement behavior first in Rust core API modules: crates/core/src/api/ and related core modules such as crates/core/src/api/runtime/, crates/core/src/codec/, or crates/core/src/json.rs

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
**/*.rs

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

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

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

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

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

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

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

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

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/{Cargo.toml,**/*.rs}

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{h,hpp,c,cpp,rs}

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/core/**/*.rs

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

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.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:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. 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/core/src/api/runtime.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/launcher.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/src/server.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{py,txt,toml,cfg,yaml,yml}

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/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 as release/<major>.<minor>.

**/Cargo.toml: Maintain Cargo.toml [workspace.package].version as the source of truth for the Rust workspace and Python build versioning
Keep Cargo.toml [workspace.dependencies] self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, run cargo check --workspace to refresh Cargo.lock

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/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/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.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:

  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

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

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
{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/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
🔇 Additional comments (18)
crates/core/src/api/runtime.rs (1)

23-23: LGTM!

crates/core/src/api/runtime/scope_stack.rs (3)

260-262: LGTM!


281-287: LGTM!

Also applies to: 386-388


289-308: 🩺 Stability & Availability

RAII restore is correct and panic-safe. replace() captures the prior override and Drop restores it unconditionally, so nesting and unwinding both recover the previous scope stack. The only caller here is the synchronous native callback wrapper in crates/core/src/plugin/dynamic/native.rs, so the thread-local override is intentionally bounded.

crates/core/Cargo.toml (2)

78-86: Native-only dependencies are still unconditional.

dynamic::native is non-wasm gated, so nemo-relay-plugin, libloading, semver, and sha2 should stay under a non-wasm target dependency section if wasm builds must avoid native-only resolution. This matches the prior review finding; please verify this is intentional before leaving them in [dependencies].


123-126: LGTM!

crates/core/src/plugin/dynamic/native.rs (4)

88-93: Callback closures still need to keep the library loaded.

NativeCallbackUserData only stores ptr and free_fn; registered callbacks can still outlive the activation/library if configuration is not cleared first. This is the same previously flagged callback-lifetime issue. As per path instructions, "Pay close attention to ... callback lifetimes," and as per coding guidelines, "Bindings should preserve callback and future lifetimes".

Also applies to: 978-1001

Sources: Coding guidelines, Path instructions


1430-1432: Free native outputs before fallible decoding.

These paths still decode with ? before freeing host-owned native output pointers, so malformed UTF-8/JSON can leak allocations. This matches the earlier native-output cleanup finding.

Also applies to: 1547-1548, 1609-1611, 1666-1678


1499-1500: Restore scope-stack binding in helper threads.

The std::thread::spawn(... block_on(next(...))) paths still lose task/thread-local scope state before downstream execution or stream polling. This is the previously flagged propagation gap. As per path instructions, "Pay close attention to task-local/thread-local scope propagation," and as per coding guidelines, "Keep async behavior on the existing tokio-based model."

Also applies to: 1760-1761, 1839-1840, 2021-2022

Sources: Coding guidelines, Path instructions


1-2: 📐 Maintainability & Code Quality

Confirm the required core/Rust validation matrix.

The PR notes focused cargo test -p ... and cargo check, but this touches crates/core native FFI/runtime code. Please confirm cargo fmt --all, cargo clippy --workspace --all-targets -- -D warnings, just test-rust, and the affected binding matrix passed. As per coding guidelines, "Any Rust change must run just test-rust", "cargo fmt --all", and "cargo clippy --workspace --all-targets -- -D warnings"; as per path instructions, "Changes to crates/core or crates/adaptive must run the full language matrix".

Sources: Coding guidelines, Path instructions

crates/core/tests/integration/native_plugin_tests.rs (1)

1-23: Gate native-plugin integration tests off wasm targets.

This test imports std::process::Command and load_native_plugins; the native loader is non-wasm only. Same prior wasm-gating finding still applies.

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

22-28: LGTM!

crates/core/tests/fixtures/native_plugin/Cargo.toml (1)

1-18: LGTM!

crates/core/tests/fixtures/native_plugin/src/lib.rs (1)

1-445: LGTM!

crates/cli/src/plugins/lifecycle.rs (1)

377-381: Only require manifest_ref for native components.

PluginActivation::initialize() only reads manifest_ref after filtering to DynamicPluginKind::RustDynamic, but Line 380 now fails every enabled record. An enabled worker record with source.manifest_ref = None will abort startup even though the worker path never consumes that field.

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

419-423: Assert the native component kind here.

This test locks plugin_id, manifest_ref, and config, but not the DynamicPluginKind that gateway startup branches on. A misclassified native record would still pass here and only fail later during activation.

As per path instructions, "Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant."

Source: Path instructions

crates/cli/src/launcher.rs (1)

104-112: Keep --dry-run side-effect free.

TransparentRun::new() resolves dynamic_plugins before Line 143 returns on dry runs, and active_dynamic_plugin_components() persists touched scopes via load_and_hydrate_scopes(). run --dry-run can still rewrite lifecycle state even though no gateway or child process starts.

crates/cli/src/server.rs (1)

246-273: Call NativePluginActivation::clear() on failure and teardown.

load_native_plugins() registers native kinds globally. Here, an initialize_plugins_exact() failure drops native without clearing it, and clear() does the same with self.native.take(). That can leak native registrations into later gateway startups in the same process.

Also applies to: 280-289

Comment thread crates/cli/tests/coverage/server_tests.rs
Comment thread crates/core/tests/integration/native_plugin_tests.rs
@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from ca21ca9 to 83cc009 Compare June 26, 2026 16:16
@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 83cc009 to 239e3c2 Compare June 26, 2026 16:21
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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/cli/tests/coverage/launcher_tests.rs`:
- Around line 1155-1157: The dry-run test is hard-coding fixture compatibility
in the dynamic manifest instead of deriving it from the crate version. Update
the fixture generation/parsing logic in launcher_tests.rs so the [compat] relay
range comes from [workspace.package].version (the source of truth) rather than a
literal >=0.5,<1.0 string, keeping the manifest aligned with version bumps and
preserving the lifecycle-state assertion path.

In `@crates/cli/tests/coverage/server_tests.rs`:
- Around line 1728-1741: The test around serve_listener_with_dynamic should not
keep the oneshot sender alive after calling the server helper, because that can
block failure detection if the call unexpectedly succeeds. Update the test to
explicitly drop the shutdown sender immediately after creating the channel (or
otherwise ensure it is out of scope before awaiting
serve_listener_with_dynamic), while keeping the existing error assertion
behavior intact so the test fails fast. Use the oneshot::channel setup,
shutdown_rx, and serve_listener_with_dynamic as the key locations to adjust.

In `@crates/core/src/plugin/dynamic/native.rs`:
- Around line 42-45: The helper-thread setup in native callback handling is only
capturing the thread binding, so when the callback runs under with_scope_stack()
it loses the visible override stack stored in SCOPE_STACK_OVERRIDE. Update the
native_*_next helper-thread propagation path to capture and restore the active
scope stack state as well as the thread binding, using the existing scope stack
helpers in the runtime module (for example capture_thread_scope_stack,
restore_thread_scope_stack, and scope_stack_active) around the native callback
setup so isolated scope parentage is preserved.
- Around line 155-165: Free the native output buffer in the non-Ok path of the
validation flow so it does not leak when `validate` fails after populating
`out`. In `native_validate` (the block that calls `validate`, checks
`NemoRelayStatus::Ok`, and returns `native_error_diagnostic`), ensure `out` is
released before the early return, matching the existing
`native_string_free(config_json)` cleanup pattern and using the same native free
helper for the allocated string.

In `@crates/core/tests/integration/native_plugin_tests.rs`:
- Around line 186-193: The native plugin test currently only checks that the
emitted thread-stack event is isolated from the fixture stack, but it does not
verify the expected positive parent linkage for normal native callback
emissions. Update the `native_plugin_tests` subcase around `flush_subscribers`
and `assert_not_parent` to also assert the correct explicit thread-stack parent
for the caller-owned stack on the relevant event, using the same event
collection and UUID setup in `thread_events`/`thread_outer_uuid` so the test
covers both isolation and intended propagation.
🪄 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: f89f1160-ff42-4e30-bbeb-10d19177e913

📥 Commits

Reviewing files that changed from the base of the PR and between ca21ca9 and 83cc009.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (17)
  • crates/cli/src/config.rs
  • crates/cli/src/launcher.rs
  • crates/cli/src/main.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/src/server.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (21)
crates/core/src/api/**/*.rs

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

Implement behavior first in Rust core API modules: crates/core/src/api/ and related core modules such as crates/core/src/api/runtime/, crates/core/src/codec/, or crates/core/src/json.rs

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
**/*.rs

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

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

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

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

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

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

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

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

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/{Cargo.toml,**/*.rs}

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{h,hpp,c,cpp,rs}

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/core/**/*.rs

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

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.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:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. 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/core/src/api/runtime.rs
  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/src/main.rs
  • crates/cli/src/config.rs
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/src/launcher.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/src/plugins/lifecycle.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/cli/src/server.rs
  • crates/core/Cargo.toml
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/native.rs
**/*.{py,txt,toml,cfg,yaml,yml}

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

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/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 as release/<major>.<minor>.

**/Cargo.toml: Maintain Cargo.toml [workspace.package].version as the source of truth for the Rust workspace and Python build versioning
Keep Cargo.toml [workspace.dependencies] self-references aligned with the workspace version when the workspace version changes
After updating workspace package entries, run cargo check --workspace to refresh Cargo.lock

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/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/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/Cargo.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:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/Cargo.toml
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

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

Files:

  • crates/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/core/Cargo.toml
{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/core/tests/fixtures/native_plugin/Cargo.toml
  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/native_plugin_tests.rs
**/*config*.{rs,ts,py,go,js,json,yaml,yml}

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

Ensure dynamic config shape still matches the documented canonical model

Files:

  • crates/cli/src/config.rs
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • crates/cli/tests/coverage/launcher_tests.rs
  • crates/cli/tests/coverage/plugins_lifecycle_tests.rs
  • crates/cli/tests/coverage/main_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
🔇 Additional comments (21)
crates/core/tests/integration/native_plugin_tests.rs (2)

59-83: Duplicate: protect global cleanup with RAII.

The test still relies on tail cleanup; a panic before Lines 347-351 can leave the subscriber/plugin configuration registered while the activation unwinds.

Also applies to: 347-351


4-52: LGTM!

Also applies to: 354-1041

crates/core/tests/fixtures/native_plugin/Cargo.toml (1)

1-18: LGTM!

crates/core/tests/fixtures/native_plugin/src/lib.rs (2)

1-2: 📐 Maintainability & Code Quality

Confirm required Rust validation before merge.

The PR validation lists focused cargo test -p ... / cargo check, but this Rust/FFI fixture also needs the repository-required Rust formatting, linting, and full Rust test entrypoint.

As per coding guidelines, "Any Rust change must run just test-rust", "Any Rust change must run cargo fmt --all", and "Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings".

Source: Coding guidelines


4-445: LGTM!

crates/cli/src/plugins/lifecycle.rs (2)

377-385: Prior concern resolved: manifest_ref is now required only for RustDynamic and cloned (optional) for Worker, so enabled worker records without a manifest reference no longer fail startup.


343-376: LGTM!

Also applies to: 386-389

crates/cli/tests/coverage/plugins_lifecycle_tests.rs (2)

419-429: Prior concern resolved: line 422 now asserts active[0].kind == DynamicPluginKind::RustDynamic, covering the gateway startup branching.


306-352: LGTM!

Also applies to: 385-418, 430-526

crates/core/src/api/runtime.rs (1)

23-23: LGTM!

crates/core/Cargo.toml (2)

119-122: LGTM!


156-159: 📐 Maintainability & Code Quality

No change needed for sha2 = "0.11" The native-only dependency block is correctly gated, and sha2 0.11.0 is available on crates.io.

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

778-780: LGTM!

crates/cli/src/main.rs (1)

199-204: LGTM!

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

90-93: LGTM!

Also applies to: 108-161, 172-202

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

190-192: Already flagged: pin this fixture to the current crate version.

relay = ">=0.5,<1.0" can drift from the workspace version and fail before the missing-library assertion is exercised.

crates/core/src/api/runtime/scope_stack.rs (1)

260-262: LGTM!

Also applies to: 281-309, 386-388

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

22-28: LGTM!

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

1-3: 📐 Maintainability & Code Quality

Confirm the required Rust/core validation before merge.

The PR objectives list targeted package tests/checks, but this change touches crates/core runtime/FFI behavior and CLI Rust wiring. Please confirm the repo-required Rust validation and affected binding matrix were run before merge. As per coding guidelines, “Any Rust change must run just test-rust”, “Run cargo fmt --all”, and “Run cargo clippy --workspace --all-targets -- -D warnings”. As per path instructions, changes to crates/core must run the full language matrix.

Sources: Coding guidelines, Path instructions

crates/cli/src/launcher.rs (1)

25-25: LGTM!

Also applies to: 91-125, 149-152, 162-179, 296-309

crates/cli/src/server.rs (1)

12-17: LGTM!

Also applies to: 29-29, 44-48, 67-91, 218-298

Comment thread crates/cli/tests/coverage/launcher_tests.rs
Comment thread crates/cli/tests/coverage/server_tests.rs Outdated
Comment thread crates/core/src/plugin/dynamic/native.rs
Comment thread crates/core/src/plugin/dynamic/native.rs
Comment thread crates/core/tests/integration/native_plugin_tests.rs
@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 239e3c2 to 8a6b611 Compare June 26, 2026 16:45
@willkill07 willkill07 removed the request for review from a team June 26, 2026 16:52
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown

Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07 willkill07 force-pushed the wkk_dynamic-plugin-3-native-loader branch from 8a6b611 to e7bd017 Compare June 26, 2026 17:09
@willkill07 willkill07 removed the DO NOT MERGE PR should not be merged; see PR for details label Jun 26, 2026
@github-actions

Copy link
Copy Markdown

License Diff

Compared against origin/main.

Lockfile license changes

Lockfile License Changes

Rust

Added

  • None

Removed

  • None

Updated/Changed

  • None

Node

Added

  • None

Removed

  • None

Updated/Changed

  • None

Python

Added

  • None

Removed

  • None

Updated/Changed

  • None
Status output
[license-diff] selected languages: rust, node, python
[license-diff] generating current inventory
[license-diff] current: generating Rust inventory
[license-diff] current: Rust inventory complete (344 packages)
[license-diff] current: generating Node inventory
[license-diff] current: Node inventory complete (364 packages)
[license-diff] current: generating Python inventory
[license-diff] current: Python inventory complete (104 packages)
[license-diff] current inventory complete
[license-diff] checking out base ref origin/main into a temporary worktree
[license-diff] base: generating Rust inventory
[license-diff] base: Rust inventory complete (344 packages)
[license-diff] base: generating Node inventory
[license-diff] base: Node inventory complete (364 packages)
[license-diff] base: generating Python inventory
[license-diff] base: Python inventory complete (104 packages)
[license-diff] base inventory complete
[license-diff] removing temporary base worktree
[license-diff] comparing inventories
[license-diff] rendering Markdown output
[license-diff] done

@afourniernv afourniernv self-requested a review June 26, 2026 17:23
@willkill07

Copy link
Copy Markdown
Member Author

/merge

@rapids-bot rapids-bot Bot merged commit 10a0543 into NVIDIA:main Jun 26, 2026
69 of 71 checks passed
rapids-bot Bot pushed a commit that referenced this pull request Jun 26, 2026
#### Overview

Add the out-of-process worker protocol and Rust worker SDK layer.

Stack dependency: this PR cannot be merged until parent stacked PR #307 is merged: #307

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

#### Details

- Add `nemo-relay-worker-proto` with `nemo.relay.worker.v1` protobuf services and messages.
- Add `nemo-relay-worker` as the Rust SDK for gRPC worker plugins.
- Add protocol stability tests and worker SDK helpers for registration, continuations, streaming, and host runtime calls.

Validation run across the completed stack:

- `cargo test -p nemo-relay-types`
- `cargo test -p nemo-relay-plugin`
- `cargo test -p nemo-relay-worker-proto`
- `cargo test -p nemo-relay-worker`
- `cargo check -p nemo-relay-cli`

#### Where should the reviewer start?

Start with `crates/worker-proto/proto/nemo/relay/worker/v1/plugin_worker.proto`, then review `crates/worker/src/lib.rs`.

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

- Relates to: #302
- Relates to: #230



## Summary by CodeRabbit

* **New Features**
  * Added out-of-process worker plugins with a new gRPC-based SDK/protocol.
  * Expanded supported worker runtimes to include Rust and generic command-based workers.
  * Introduced JSON envelope helpers and added scope + streaming callback support for worker execution flows.
* **Bug Fixes**
  * Updated plugin compatibility validation to require the `grpc-v1` worker protocol and improved rejection messaging for unsupported values.
* **Tests**
  * Expanded unit and end-to-end worker SDK coverage for new runtimes, protocol validation, and streaming behavior.
* **Chores**
  * Added new workspace crates and updated licensing, CI triggers, and release/publishing configuration.

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

Approvers:
  - Alex Fournier (https://github.com/afourniernv)
  - https://github.com/Salonijain27

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

Labels

Feature a new feature lang:rust PR changes/introduces Rust code size:XL PR is extra large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants